views:

926

answers:

5

I'm using Smarty and PHP. If I have a template (either as a file or as a string), is there some way to get smarty to parse that file/string and return an array with all the smarty variables in that template?

e.g.: I want something like this:

$mystring = "Hello {$name}. How are you on this fine {$dayofweek} morning";
$vars = $smarty->magically_parse( $string );
// $vars should now be array( "name", "dayofweek" );

The reason I want to do this is because I want users to be able to enter templates themselves and then fill them in at a later date. Hence I need to be able to get a list of the variables that are in this templates.

Let's assume that I'm only doing simple variables (e.g.: no "{$object.method}" or "{$varaible|function}"), and that I'm not including any other templates.

A: 

Try http://php.net/manual/en/function.get-defined-vars.php

Ollie Saunders
That works for the PHP variables, I want this for the Smarty variables that are defined in a template
Rory
+2  A: 

Normally I'm against regular expressions, but this looks like a valid case to me. You could use preg_match_all() to do that (If you only want variables like ${this}):

preg_match_all('\{\$(.*?)\}', $string, $matches, PREG_PATTERN_ORDER);
$variableNames = $matches[1];
soulmerge
Notes: (1) Smarty variables are {$var}, not ${var}. (2) `$matches` will be an array of arrays, so you will have to iterate over `$matches[0]` to access full matches. (3) It might be easier to capture the contents of `{` and `}` using parantheses, then accessing it using `$matches[1]` instead of using `substr()` on the full matches.
Ferdinand Beyer
@Ferdinand: Thx, updated answer.
soulmerge
You could just do $variableNames = $matches[1]; . If you want to loop over the result like you are doing, you need to use the PREG_SET_ORDER flag I think.
Tom Haigh
@Tom: Thx, it was PREG_PATTERN_ORDER, and reduced the code to two lines.
soulmerge
PREG_PATTERN_ORDER is the default, I meant that for your previous example to work you needed to specify PREG_SET_ORDER. But PREG_PATTERN_ORDER is better here
Tom Haigh
yeah that's what I was thinking of doing, I was just hoping that there would be an easy builtin smarty way of doing it.
Rory
@Rory: smarty does the processing in a single giant function, so the code for matching the variables is not isolated, but burrowed into that one. So my guess is that the function you are looking for does not exist.
soulmerge
A: 

Hello,

I think what you're looking for is the debugging console.

This console shows you all variables used within the templates involved in your webpage.

Arno
+1  A: 

If you need variables hidden in things like {if $var%2} I'd go with this kind of code :

preg_match_all('`{[^\\$]*\\$([a-zA-Z0-9]+)[^\\}]*}`', $string, $result);
$vars = $result[1];

If you also want to catch things like that : {if $var != $var2} a better version follows

function getSmartyVars($string){
  // regexp
  $fullPattern = '`{[^\\$]*\\$([a-zA-Z0-9]+)[^\\}]*}`';
  $separateVars = '`[^\\$]*\\$([a-zA-Z0-9]+)`';

  $smartyVars = array();
  // We start by extracting all the {} with var embedded
  if(!preg_match_all($fullPattern, $string, $results)){
    return $smartyVars;
  }
  // Then we extract all smarty variables
  foreach($results[0] AS $result){
    if(preg_match_all($separateVars, $result, $matches)){
      $smartyVars = array_merge($smartyVars, $matches[1]);
    }
  }
  return array_unique($smartyVars);
}
Arkh
A: 

It looks like there isn't an inbuilt way to do this.

Rory