|
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 |
dthought Smarty Regular
Joined: 21 Apr 2003 Posts: 55 Location: Melbourne, Australia
|
Posted: Tue Nov 30, 2004 11:20 pm Post subject: Improvments to register_resource / resource behaviour |
|
|
Ahh, the joys of using register_resource.
At the moment I'm working with a project that reads templates from two separate places - a project-specific templates folder and a 'core' folder that is common across other projects using the same framework (for stuff like login, error messages, etc).
At the moment I access these templates by doing stuff like
{include file="core:ext/templates/mytemplate.tpl"} which is all lovely.
However, if I add another resource, eg. someotherplace:othertemplate.tpl, then I have to copy the same four callback functions but give them different names in PHP, even if their internals are the same, save for where they point the "true" directory: to.
A nice way I thought of to get around this would be to have a configurable lookup array, something like:
array(
'core' => '/path/to/core',
'otherplace => '/path/elsewhere'
);
and so on, with the keys matching the relevant directory: name. However, it would appear that short of hacking Smarty to reveal a few more of its scary internal variables, there is no way to determine which resource key is currently being called!
So a nice feature I would like to see is that when Smarty runs its callback, it sends a fourth optional variable which contains the current resource's key name. That would make life so much easier and cleaner! (-;
Hopefully that wasn't too long winded... if I can clarify anything there, please ask! |
|
Back to top |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed Dec 01, 2004 12:01 am Post subject: |
|
|
It's a nice idea but I unless I am missing something, I don't think it makes much sense. If you register a callback with Smarty (say "core") then Smarty necessarily calls resource functions with "core" already assumed as part of the function name. Why pass the very same name (essentially) of the function you are calling? A function *must* know its name!
I think what you possibly want is a more generic resource, say "Local" (or whatever) that handles the mappings you mention. You would then reference your templates using something like file="local:core/ext/templates/mytemplate.tpl". Note that you can use any funky syntax you are willing to parse for the filename so something like "local:core|ext/templates/mytemplate.tpl" or "local:core:ext/templates/mytemplate.tpl" can be made to work very easily.
If you need an example of custom filename-syntax parsing, you can look here. |
|
Back to top |
|
dthought Smarty Regular
Joined: 21 Apr 2003 Posts: 55 Location: Melbourne, Australia
|
Posted: Wed Dec 01, 2004 3:16 am Post subject: |
|
|
Thanks for your reply, boots
Not quite what I was thinking of though.
Let's say this is part of some framework code, which is passed to Smarty to register resources required for a project:
Code: | $this->_config_elements["_SMARTY"]["RESOURCE"] = array(
"core" => array(
"smarty_resource_core_source",
"smarty_resource_core_timestamp",
"smarty_resource_core_secure",
"smarty_resource_core_trusted"
),
"base" => array(
"smarty_resource_base_source",
"smarty_resource_base_timestamp",
"smarty_resource_base_secure",
"smarty_resource_base_trusted"
)
); |
And the associated function callbacks
Code: | function smarty_resource_core_source($tpl_name, &$tpl_source, &$smarty)
{
$file = map_path_core($tpl_name);
if (is_file($file)) {
$tpl_source = $smarty->_read_file($file);
return TRUE;
}
return FALSE;
}
function smarty_resource_core_timestamp($tpl_name, &$tpl_timestamp, &$smarty)
{
$file = map_path_core($tpl_name);
if (is_file($file)) {
$tpl_timestamp = filemtime($file);
return TRUE;
}
return FALSE;
}
function smarty_resource_core_secure($tpl_name, &$smarty)
{
return TRUE;
}
function smarty_resource_core_trusted($tpl_name, &$smarty)
{
return TRUE;
}
function map_path_core($path)
{
return realpath($_SERVER['DOCUMENT_ROOT'] . "/some/path/" . $path);
}
//-----------------------------------------------------------------------------//
function smarty_resource_base_source($tpl_name, &$tpl_source, &$smarty)
{
$file = map_path_base($tpl_name);
if (is_file($file)) {
$tpl_source = $smarty->_read_file($file);
return TRUE;
}
return FALSE;
}
function smarty_resource_base_timestamp($tpl_name, &$tpl_timestamp, &$smarty)
{
$file = map_path_base($tpl_name);
if (is_file($file)) {
$tpl_timestamp = filemtime($file);
return TRUE;
}
return FALSE;
}
function smarty_resource_base_secure($tpl_name, &$smarty)
{
return TRUE;
}
function smarty_resource_base_trusted($tpl_name, &$smarty)
{
return TRUE;
}
function map_path_base($path)
{
return realpath($_SERVER['DOCUMENT_ROOT'] . "/another/different/path/" . $path);
} |
Now, the only difference between those two sets of four functions is the path in map_path_[resource name]. What I would like to do, is rather than have to have four functions whose purpose is virtually identical save for one minor change, is have say, a lookup array like this:
Code: | $resource_lookup = array(
'core' => $_SERVER['DOCUMENT_ROOT'] . "/some/path/",
'base' => $_SERVER['DOCUMENT_ROOT'] . "/another/different/path/"
); |
And have something like a fourth parameter sent from Smarty when it uses this resource, as in:
Code: | function smarty_resource_source($tpl_name, &$tpl_source, &$smarty, $resource_name) { } |
So I can then do this:
Code: | $file = map_path_core($tpl_name, $resource_lookup[$resource_name]); |
And just add to my config array all the paths as needed, saving lots of parsing time from PHP and lots of code spaghetti headaches. I believe that something like this would still allow the old way to work, the only difference is that the functions are now aware what their executing resource is (-:
Make sense now? Bad idea? Good idea? |
|
Back to top |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Wed Dec 01, 2004 3:54 am Post subject: |
|
|
I think (think, mind-you) that I understand what you are getting at -- basically the same thing you said in your first post, yes? I do see the merit of a generalized filesystem mapper as you suggest. Yet tell me, how would you call a resource? I assume:
{include file="core:foo.tpl"}
{include file="base:foo.tpl"}
Okay, that's all fine and good but how does that get called behind the scenes? Are you suggesting a default resource handler that is called in the case where a resource isn't found? If not, I don't see how it might work -- what if I don't want a filesystem backed resource? Besides, doesn't that just amount to the idea I suggested earlier? If you set default_resource_handler to (say) 'local' then you can use paths like "core|foo.tpl" (or even "core/foo.tpl") and your local: resource can take care of the details of the real path mapping.
I do apologize if I (continue) to fail to see what you are suggesting -- I do think it is a good idea to generalize the mapping, I'm just not entirely sure I see how you would have it implemented, syntax wise. |
|
Back to top |
|
dthought Smarty Regular
Joined: 21 Apr 2003 Posts: 55 Location: Melbourne, Australia
|
Posted: Mon Dec 13, 2004 4:52 am Post subject: |
|
|
boots wrote: | {include file="core:foo.tpl"}
{include file="base:foo.tpl"}
Okay, that's all fine and good but how does that get called behind the scenes? Are you suggesting a default resource handler that is called in the case where a resource isn't found? |
What I am suggesting, is that Smarty pass an additional, and optional, variable to its callback functions that contains the name before the : that was called.
So, for example with core:, it would pass an extra variable to the callback functions that contains the string, 'core'. You could then write your function to use this string variable to do a generalised lookup in a config array.
I believe that this allows you to write things as they are currently - with a separate set of callbacks for each resource - or with the extra variable being passed, one set of callbacks that can use the called resource's name to determine where it should look.
It's a bit of a sod to explain... hopefully though I'll eventually write something which has enough clarity to it |
|
Back to top |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Mon Dec 13, 2004 7:16 am Post subject: |
|
|
Hi again dthought!
dthought wrote: | It's a bit of a sod to explain... hopefully though I'll eventually write something which has enough clarity to it |
Yes, I think you should write an example resource that shows how you think it would work. I still don't get it. If you write call "core:foo.tpl" then Smarty will call (for example) smarty_resource_core_source(). If the function already has "core" in its name, why tell it that it is being called with "core"? That's the part I am not following. I feel like we really aren't seeing eye-to-eye on this one |
|
Back to top |
|
themightychris Smarty Rookie
Joined: 02 Jan 2005 Posts: 6 Location: Bucks County, Pennsylvania, US
|
Posted: Wed Jan 05, 2005 8:38 am Post subject: |
|
|
I understand what he means I think, maybe I can make it clearer.
Quote: |
Yes, I think you should write an example resource that shows how you think it would work. I still don't get it. If you write call "core:foo.tpl" then Smarty will call (for example) smarty_resource_core_source().
|
the core in "core:foo.tpl" is from the first parameter of register_resource but the function names are independently specified in the second parameter.
say, for example, that I wanted to impliment a database resource that could work with several different dbms's. Most of the code would be the same, except for a couple different connection lines, so creating and maintaining several different instances of essentially the same functions would be a pain.
The cleanest thing to do would be mapping resources like mysql: pgsql: and mssql: to the same functions.
then you could have for your function
Code: |
function db_get_template ($tpl_name, &$tpl_source, &$smarty_obj, $resource_name)
{
if($resource_name == "mysql) {
$link = mysqlconnect(...
...
}
...
}
|
You would need to add an additional optional paarameter to register_resource specifying whether or not this parameter should be passed (to each callback)
Now, what boots is saying, is why don't you just have a generic resource name and put this information into the template name part of the string and just parse it out in the beginning, for my example something like: "database:mysql/templatename"
and then just have at the top of your function
Code: |
list($resource_name, $tpl_name) = explode("/", $tpl_name, 2);
|
This would accomplish the exact same thing, but without a ton of modification to smarty. The only downsides are it is 1 extra line of code for you and, this could be very important to you, the syntax used in the template is not as neat
mysql:templatename vs database:mysql/templatename
I say dthought should just use the second one |
|
Back to top |
|
boots Administrator
Joined: 16 Apr 2003 Posts: 5611 Location: Toronto, Canada
|
Posted: Fri Jan 07, 2005 2:07 am Post subject: |
|
|
IMHO I'd say that the proper way to map functions in this case would be to use wrapper functions:
[php:1:0c6a45a9d0]<?php
function mysql_get_template ($tpl_name, &$tpl_source, &$smarty_obj, $resource_name)
{
return db_get_template($tpl_name, $tpl_source, $smarty_obj, $resource_name)
}
?>[/php:1:0c6a45a9d0]
or if you are really lazy and need this all the time, write an extended register_resrouce method in an extended Smarty class that had better mapping features. Don't forget that you aren't limited to db:mysql/foo/bar syntax. You could also use db:mysql:foo/bar if that makes more sense for you. Of course, having the connection type specified (mysql, etc) seems a little too much for the template itself. Well, I feel like I'm beating this poor horse at this point so I will stop here |
|
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
|
|