Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

generic database template resource example

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Jun 18, 2003 12:56 am    Post subject: generic database template resource example Reply with quote

Hi all.

The following is an example of a database resource plugin that can load a template from any field in any table of a connected database. This is useful, for example, if you want to quickly expose an existing database to Smarty without altering it or designing any specialized base classes (or resources) to access it.

This is intended only as an illustration--the code has been simplified and error checking removed. Further, this is not a complete example as I am including only a sample of the resource plugin code. The code that I am not including I assume you already have in another form and can adapt it to this use.

Example

Lets say you have a CMS database with an article table. This table has a field item that you want Smarty to access as a template source. In this example, there is additionally a unique varchar field tag which acts as a short, friendly name for the article.

Assume your application determines the desired article like so:

Code:
$tag = $_REQUEST['tag'];


Using this resource, you could access the template as follows:
Code:
$smarty->display("userdb:article/item?tag='$tag'");


If your table requires a narrower search, you add more conditionals:
Code:
$smarty->display("userdb:article/item?tag='$tag'&category_id=$category_id");


aside: with a bit of tweaking, you might be able to get this to handle a more sophisticated query syntax like XPath


How It Works

The real work is isolated in smarty_resource_userdb_fetch().

First, a simple parsing of the $tpl_name is done to break out the table name, source field name, etc. NB. lack of error checking!

Then, if not assigned, $smarty->userdb_driver is created using a custom db wrapper. I assume that you are using one yourself, so I've abstracted most of its details out of this plugin. For one thing, this assumed wrapper knows how to login and create a connection to the user database and further, it stores that connection in a member variable and disconnects from the db when the driver object is destroyed--but you are free to implement your driver any way you please Smile

Finally, the driver is called for results, returning a 2d array (assumed associative). The driver is expected to throw errors as appropriate. I did leave sample SQL in this example code to show the basic premise of how the wrapper should handle the request -- it can and should be removed from a working implementation (especially since the SQL shown uses specific MySQL syntax in the LIMIT clause).

Because all of the work is done in smarty_resource_userdb_fetch(), very little is needed in the functions that Smarty actually requires of the resource.

Surprisingly, the _timestamp function does a little bit more (but not much), simply because the _fetch function was really designed to support the _source function instead of being fully generalized. As a result, it first replaces the source_template field in the requested $tpl_name with (again MySQL specific) 'UNIX_TIMESTAMP( timestamp )'. In our example, this causes the driver to fetch the timestamp field from the article table if it exists. If it doesn't exist, it returns with the default value that it was passed: in this case, microtime().

This means that if you don't add a timestamp field to your table, this still works, but your templates will always be forced to recompile (which in some cases, may be desirable).

Quote:
aside: You can use the *new* (CVS only) default_resource_type to make your syntax that much simpler Smile

Code:
$smarty->default_resource_type = 'userdb';
$smarty->display("article/item?tag='$tag'");


A lot of verbage for a very slender bit of code...[php:1:acaaa0f209]<?php

// load your custom db handler
require_once MY_LIBS_DIR . 'driver/storage/userdb.inc';

/*
* Smarty plugin
* -------------------------------------------------------------
* Type: resource
* Name: userdb
* Purpose: read user maintained source as a template
* $tpl_name is parsed as a uri type of string where
* the path to the template field is encoded as:
*
* table/source_field?field=condtional&field=conditional...
*
* results in:
* SELECT source_field FROM table WHERE conditions...
* -------------------------------------------------------------
*/
function smarty_resource_userdb_fetch($tpl_name, &$tpl_source, &$smarty, $default=false)
{
$_url = parse_url($tpl_name);

// (required) expected syntax: table/source_field
$_path_items = explode('/', $_url['path']);
$table = $_path_items[0];
$source = $_path_items[1];

// all contitionals are separated by AND (&)
// (optional) expected syntax: field=condition&field=condition...
$where = '';
$i = 0;
$_query_items = explode('&', $_url['query']);
foreach($_query_items as $_query) {
if ($i++ > 0) {
$where .= ' AND ';
}
$_query_item = explode('=', $_query);
$where .= $_query_item[0] . '=' . $_query_item[1];
}
if ( $i > 0 )
{
$where = "WHERE $where";
}

if (!isset($smarty->userdb_driver)) {
$smarty->userdb_driver = new UserDBStorageDriver;
}

$tpl_source = $smarty->userdb_driver->data_get("SELECT $source FROM $table $where LIMIT 1;");
if ($tpl_source) {
$tpl_source = $tpl_source[0][0];
return true;
} else {
return $default;
}
}

function smarty_resource_userdb_source($tpl_name, &$tpl_source, &$smarty)
{
if (smarty_resource_userdb_fetch($tpl_name, $tpl_source, $smarty)) {
$tpl_source = stripslashes($tpl_source);
return true;
}
return false;
}

function smarty_resource_userdb_timestamp($tpl_name, &$tpl_source, &$smarty)
{
$_url = parse_url($tpl_name);
// (required) expected syntax: table/source_field
$_path_items = explode('/', $_url['path']);
$table = $_path_items[0];
$source = 'UNIX_TIMESTAMP(timestamp)';
$tpl_name = "$table/$source?" . $_url['query'];
return smarty_resource_userdb_fetch($tpl_name, $tpl_source, $smarty, microtime());
}

function smarty_resource_userdb_secure($tpl_name, &$smarty)
{
return true;
}
function smarty_resource_userdb_trusted($tpl_name, &$smarty)
{
return true;
}

?>[/php:1:acaaa0f209]


Last edited by boots on Wed May 05, 2004 8:22 pm; edited 1 time in total
Back to top
View user's profile Send private message
Hpatoio
Smarty Rookie


Joined: 29 Apr 2003
Posts: 25
Location: Italy

PostPosted: Wed May 05, 2004 9:09 am    Post subject: decleared twice ? Reply with quote

Hej boots ... I was just looking at your DB resource example.

But, is it right to have the function smarty_resource_userdb_timestamp twice ? Shocked

Ciao

/Simone
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed May 05, 2004 8:24 pm    Post subject: Re: decleared twice ? Reply with quote

Hpatoio wrote:
is it right to have the function smarty_resource_userdb_timestamp twice ?


d'oh? Its fixed now. I must been doing some really fancy copy+pasting when getting the code into the post. sheesh.

Thanks Hpatoio!
Back to top
View user's profile Send private message
webadept
Smarty Regular


Joined: 09 Mar 2004
Posts: 41

PostPosted: Wed Jun 30, 2004 4:13 pm    Post subject: Reply with quote

Umm.. okay.. that's really cool.. where the heck is that paypal button.. i know its around here somewhere.. Smile

I wasn't looking for this on my visit today, but it sure finds me at a great time.. very cool Boots, very cool indeed.

It crosses my mind that this would be exelent for the WML adaptation thing I'm working on right now.
Back to top
View user's profile Send private message
rockyraccoon
Smarty Rookie


Joined: 10 Jan 2006
Posts: 8

PostPosted: Tue Jan 17, 2006 9:09 pm    Post subject: Reply with quote

Followed the instructions explicitly...

I created a file called: function.db.php in libs/plugins

Then included this code:

$tag = '3558';
$smarty->default_resource_type = 'userdb';
$smarty->display("templates/data?id='$tag'");

This is my error:
Warning: Smarty error: unable to read resource: "pro_templates/data?id='3558'" in /home/virtual/site1/fst/var/www/html/inc/smarty/libs/Smarty.class.php on line 1095

Been struggling for days, any help is appreciated...
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Jan 18, 2006 2:55 am    Post subject: Reply with quote

rockyraccoon wrote:
I created a file called: function.db.php in libs/plugins


Hi.

Don't you mean resource.userdb.php ?

rockyraccoon wrote:
Then included this code:

$tag = '3558';
$smarty->default_resource_type = 'userdb';
$smarty->display("templates/data?id='$tag'");

This is my error:
Warning: Smarty error: unable to read resource: "pro_templates/data?id='3558'" in /home/virtual/site1/fst/var/www/html/inc/smarty/libs/Smarty.class.php on line 1095


Why does the error message say "pro_templates/data?id='3558'" but you wrote $smarty->display("templates/data?id='$tag'"); ? And I assume that you have a table (either templates or pro_templates I guess) with a field data that has the template code for record id "3558" ?
Back to top
View user's profile Send private message
rockyraccoon
Smarty Rookie


Joined: 10 Jan 2006
Posts: 8

PostPosted: Wed Jan 18, 2006 6:38 pm    Post subject: Reply with quote

You are correct, the table/row/field is there... I renamed the plugin like you said, and finally got something new, although still an error...

Fatal error: Cannot instantiate non-existent class: userdbstoragedriver in /home/virtual/site1/fst/var/www/html/inc/smarty/libs/plugins/resource.userdb.php on line 47
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Jan 18, 2006 6:59 pm    Post subject: Reply with quote

rockyraccoon wrote:
Fatal error: Cannot instantiate non-existent class: userdbstoragedriver in /home/virtual/site1/fst/var/www/html/inc/smarty/libs/plugins/resource.userdb.php on line 47


Quote:
Then, if not assigned, $smarty->userdb_driver is created using a custom db wrapper. I assume that you are using one yourself, so I've abstracted most of its details out of this plugin. For one thing, this assumed wrapper knows how to login and create a connection to the user database and further, it stores that connection in a member variable and disconnects from the db when the driver object is destroyed--but you are free to implement your driver any way you please icon_smile.gif

Finally, the driver is called for results, returning a 2d array (assumed associative). The driver is expected to throw errors as appropriate. I did leave sample SQL in this example code to show the basic premise of how the wrapper should handle the request -- it can and should be removed from a working implementation (especially since the SQL shown uses specific MySQL syntax in the LIMIT clause).


You are supposed to provide that yourself. This was all intended as a sample as to how you might go about creating a generic db based resource handler with custom "filename" parsing. It is not intended as a drop-in working package -- you have to adapt it to your own situation.
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP