|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed Jun 18, 2003 12:56 am Post subject: generic database template resource example |
|
|
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
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
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 |
|
Hpatoio Smarty Rookie
Joined: 29 Apr 2003 Posts: 25 Location: Italy
|
Posted: Wed May 05, 2004 9:09 am Post subject: decleared twice ? |
|
|
Hej boots ... I was just looking at your DB resource example.
But, is it right to have the function smarty_resource_userdb_timestamp twice ?
Ciao
/Simone |
|
Back to top |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed May 05, 2004 8:24 pm Post subject: Re: decleared twice ? |
|
|
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 |
|
webadept Smarty Regular
Joined: 09 Mar 2004 Posts: 41
|
Posted: Wed Jun 30, 2004 4:13 pm Post subject: |
|
|
Umm.. okay.. that's really cool.. where the heck is that paypal button.. i know its around here somewhere..
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 |
|
rockyraccoon Smarty Rookie
Joined: 10 Jan 2006 Posts: 8
|
Posted: Tue Jan 17, 2006 9:09 pm Post subject: |
|
|
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed Jan 18, 2006 2:55 am Post subject: |
|
|
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 |
|
rockyraccoon Smarty Rookie
Joined: 10 Jan 2006 Posts: 8
|
Posted: Wed Jan 18, 2006 6:38 pm Post subject: |
|
|
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 |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed Jan 18, 2006 6:59 pm Post subject: |
|
|
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 |
|
|
|
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
|
|