View previous topic :: View next topic |
Author |
Message |
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Thu Apr 17, 2008 5:57 am Post subject: list all potential smarty variables found in a template |
|
|
I would like to grab all the variables in a smarty template and use them to generate some data fields in a database.
eg
template:
Code: | {$variable name="var1"}<br />
{$variable name="var2"}<br />
{$variable name="var3"}<br /> |
generates an sql statement like so:
Code: | INSERT INTO Variables VALUES ('var1', 'var2', 'var3'); |
with some kind of code like:
(pseudocode)
Code: |
$vars;
$template = getTemplate(template.tpl);
foreach in (getTemplateVars($template) as $variable) {
$vars .= "'$variable'" . ", ";
}
$sql = "INSERT INTO Variables VALUES ($vars); |
for example.
Last edited by 3e on Fri Apr 18, 2008 1:55 am; edited 1 time in total |
|
Back to top |
|
shannera Administrator
Joined: 13 Feb 2006 Posts: 802 Location: Edertal, Germany
|
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Fri Apr 18, 2008 12:01 am Post subject: almost, but no cigar |
|
|
That's the wrong way round though...
get_template vars gives me teh vars that can be put into the template...
I need to parse the template and return all of the possible variables within... |
|
Back to top |
|
Celeb Administrator
Joined: 17 Apr 2007 Posts: 1025 Location: Vienna
|
Posted: Fri Apr 18, 2008 1:57 am Post subject: |
|
|
I suppose the easiest way to accomplish this is by parsing the compiled template (usually under a somewhat cryptic name in the template_c folder).
Something along the lines of:
Code: | $file_name = '/path/to/smarty/templates_c/file';
$fh = fopen($file_name, 'r');
$content = fread($fh, filesize($file_name));
fclose($fh);
$pattern = "/$this\->_tpl_vars\[\'(.*?)\'\]/";
$matches = array();
preg_match_all($pattern, $content, $matches);
$variables = array_unique($matches[1]);
print_r($variables); |
I've found another way, it will only work under PHP5 though. And I don't think it's any less dirty than parsing the compiled template.
Firstly, I created a class that acts like an array (implements the ArrayAccess interface) and logs all "array access". Secondly, I created a class that extends the Smarty class and kind of hi-jacked the fetch() method. Note that this array class is no actual array and causes some errors, eg when array_merge is called during the fetch(), so I have to turn off error_reporting temporarily.
Code: | <?php
class TplVarsWrapper implements ArrayAccess {
private $_data;
private $_requested = array();
function __construct($vars) {
$this->_data = $vars;
}
function report() {
return $this->_requested;
}
function offsetExists($offset) {
return isset($this->_data[$offset]);
}
function offsetGet($offset) {
if (!in_array($offset, $this->_requested))
$this->_requested[] = $offset;
return $this->_data[$offset];
}
function offsetSet($offset, $value) {
$this->_data[$offset] = $value;
}
function offsetUnset($offset) {
unset($this->_data[$offset]);
}
}
class DebugSmarty extends Smarty {
function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {
// Replace _tpl_vars by the wrapper class
$old_tpl_vars = $this->_tpl_vars;
$this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);
// Turn off error reporting
$old_error_reporting = $this->error_reporting;
$this->error_reporting = 0;
// Fetch the template
parent::fetch($resource_name, $cache_id, $compile_id, false);
// Turn error reporting back on
$this->error_reporting = $old_error_reporting;
// "Repair" tpl_vars
$this->_tpl_vars = $old_tpl_vars;
// Return array of used variables
return $this->_tpl_vars->report();
}
}
?> |
Have fun with it _________________ Darn computers always do what I tell them to instead of what I want them to do. |
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Fri Apr 18, 2008 3:13 am Post subject: |
|
|
I'm just looking for a more 'tight' solution that I can encapsulate into a function that appears 'part of smarty'
oh and we're currently only using php4!
Last edited by 3e on Fri Apr 18, 2008 3:40 am; edited 1 time in total |
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Fri Apr 18, 2008 3:13 am Post subject: |
|
|
now I'm just posting another time so i can post the url for two posts back. (5 post minimum) |
|
Back to top |
|
Celeb Administrator
Joined: 17 Apr 2007 Posts: 1025 Location: Vienna
|
Posted: Fri Apr 18, 2008 11:31 am Post subject: |
|
|
3e wrote: | Thanks heaps!
I'll have a crack at that. Was hoping there'd be a function to do it.
Surely smarty forms such a list prior to replacing variables, maybe there is a way to access it? |
No, Smarty simply fills all the variables assigned by assign() into an internal array and then accesses this array when replacing template variables.
3e wrote: | Is there a recommended way to add new functions to the smarty object? |
I'd recommend extending the Smarty class is the way to go. If you avoid using private methods and variables there (those usually begin with a "_") there should be no problem when updating your Smarty installation.
Extending classes is available in PHP4 aswell.
Outputfilters are applied to the HTML generated by Smarty before being sent to the browser. I don't think they are of any use concerning your problem. _________________ Darn computers always do what I tell them to instead of what I want them to do.
Last edited by Celeb on Tue Apr 22, 2008 11:13 pm; edited 1 time in total |
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Tue Apr 22, 2008 9:39 am Post subject: |
|
|
OK Thanks for the use of your brain.
Much appreciated. |
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Tue Apr 22, 2008 4:24 pm Post subject: |
|
|
You might take a step back and figure out why you want to do this in the first place. Assembling a SQL query from the available variables in a template is completely backwards. The template should just be handling presentation, not dictating business logic. |
|
Back to top |
|
3e Smarty Rookie
Joined: 30 May 2007 Posts: 9
|
Posted: Thu Apr 24, 2008 1:36 am Post subject: |
|
|
This would seem like wisdom.
But what I'm doing is:
the cms I'm using (cms made simple) uses an API to generate form elements which are assigned to smarty vars which appear in templates...
What I'm trying to do is build an html page, parse it and generate the associated php code with api calls, smarty templates and language information to generate that page via the cms api.
thanks. |
|
Back to top |
|
shannera Administrator
Joined: 13 Feb 2006 Posts: 802 Location: Edertal, Germany
|
Posted: Thu Apr 24, 2008 9:41 am Post subject: |
|
|
So you generate a template e.g. with a form, parse it to create PHP code out of it that creates a form? Sounds a little bit crazy for me, a shot in the head through the feet... |
|
Back to top |
|
vesech Smarty Rookie
Joined: 21 Sep 2008 Posts: 10
|
Posted: Fri Nov 28, 2008 8:47 am Post subject: |
|
|
Celeb wrote: |
I've found another way, it will only work under PHP5 though. And I don't think it's any less dirty than parsing the compiled template.
Firstly, I created a class that acts like an array (implements the ArrayAccess interface) and logs all "array access". Secondly, I created a class that extends the Smarty class and kind of hi-jacked the fetch() method. Note that this array class is no actual array and causes some errors, eg when array_merge is called during the fetch(), so I have to turn off error_reporting temporarily.
Code: | <?php
class TplVarsWrapper implements ArrayAccess {
private $_data;
private $_requested = array();
function __construct($vars) {
$this->_data = $vars;
}
function report() {
return $this->_requested;
}
function offsetExists($offset) {
return isset($this->_data[$offset]);
}
function offsetGet($offset) {
if (!in_array($offset, $this->_requested))
$this->_requested[] = $offset;
return $this->_data[$offset];
}
function offsetSet($offset, $value) {
$this->_data[$offset] = $value;
}
function offsetUnset($offset) {
unset($this->_data[$offset]);
}
}
class DebugSmarty extends Smarty {
function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {
// Replace _tpl_vars by the wrapper class
$old_tpl_vars = $this->_tpl_vars;
$this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);
// Turn off error reporting
$old_error_reporting = $this->error_reporting;
$this->error_reporting = 0;
// Fetch the template
parent::fetch($resource_name, $cache_id, $compile_id, false);
// Turn error reporting back on
$this->error_reporting = $old_error_reporting;
// "Repair" tpl_vars
$this->_tpl_vars = $old_tpl_vars;
// Return array of used variables
return $this->_tpl_vars->report();
}
}
?> |
|
Cheers for this Celeb. It made it possible for me to display a list of templates which must be used by users when setting a template (linked to a previous question here: [see next edit since I'm not allowed to post a link until I have 3 posts!]
I did notice an issue with the class you've given though, in that you return the original $this->_tpl_vars variable instead of the instantiated wrapper and throw it away too early. I've made changes as follows:
Code: |
class DebugSmarty extends Smarty {
function getUsedTemplateVars($resource_name, $cache_id = null, $compile_id = null) {
// Replace _tpl_vars by the wrapper class
$old_tpl_vars = $this->_tpl_vars;
$this->_tpl_vars = new TplVarsWrapper($this->_tpl_vars);
// Turn off error reporting
$old_error_reporting = $this->error_reporting;
$this->error_reporting = 0;
// Fetch the template
parent::fetch($resource_name, $cache_id, $compile_id, false);
// Turn error reporting back on
$this->error_reporting = $old_error_reporting;
// Take a note of the wrapper vars
$tpl_vars_wrapper = $this->_tpl_vars;
// "Repair" tpl_vars
$this->_tpl_vars = $old_tpl_vars;
// Return array of used variables
return $tpl_vars_wrapper->report();
}
}
|
Cheers again, works like a charm.
Ves. |
|
Back to top |
|
vesech Smarty Rookie
Joined: 21 Sep 2008 Posts: 10
|
|
Back to top |
|
vesech Smarty Rookie
Joined: 21 Sep 2008 Posts: 10
|
Posted: Fri Nov 28, 2008 3:42 pm Post subject: |
|
|
Gah. So close. Smarty's intelligence getting the better of this:
Code: |
{if $var1 gt 3}
{if $var2}
Var2 won't display in the list of available templates!
{/if}
{/if}
print_r($debugSmarty->getUsedTemplateVars());
Array (
[0] => [var1]
)
|
... :/
Obviously since smarty isn't going in that far (with good reason) in order for the ArrayAccess to ultimately make note of it.
Anyone see any obvious workaround to make ALL the potential template variables display? |
|
Back to top |
|
|