How to implement a template with conditions with preg_replace

I am trying to implement an admin interface where a manager can create advanced rules for creating site meta tags.

I have a function that takes a template and replaces the placeholders in it with the values ​​from the $ registry and applies modifiers if necessary.

$registy = array( 'profession_name' => 'actor', 'total_found' => 100, ); $result = preg_replace_callback('/\{([^{}:]+)(:[^{}:]+)?\}/', function($matches) use ($registry) { $result = $registry[$matches[1]] ?: $matches[0]; if (in_array($matches[2], array(':ucfirst', ':strtolower', ':strtoupper', ':lcfirst'))) { $result = call_user_func(substr($matches[2], 1), $result); } return $result; }, $template); 

Example:

Profession {name: ucfirtst} is {profession_name: strtoupper}

divided into

Profession Name - ACTOR

I am trying to implement the conditions, so one could make the following rules:

text with {placeholdes} before the condition. [{total_found}, TRUE text with {placeholders}, FALSE text with {placeholders}], ending text with {placeholders} after the condition.

Thus, my function will get the value {total_found} from the registry and depending on whether it returns true or false a string with the corresponding false or true-pattern. I am very poor at regular expressions and cannot figure out how to write this condition in regular expressions. Help me please.

UPDATE: a concrete example looks like whis:

 $template = 'Profession is {profession_name}. [{total_found}, {total_found} vacancies found, No vacancies found]. {profession_name} in your town'; 

in my callback function, I would set a condition like this

 if ($matches[condition]) // i don't no how exactly $result = $matches[true-condition]; else $result = $matches[false-condition] 

So, in the case of $registry['total_found'] = 100; the end result will be "Profession is an actor. 100 vacancies found. An actor in your city." In the case of $registry['total_found'] = 0; the end result is "The profession is an actor. No vacancies found. An actor in your city."

+2
source share
1 answer
 $available_functions = array('ucfirst', 'strtolower', 'strtoupper', 'lcfirst'); $registry = array( 'profession_name' => 'actor', 'total_found' => 100, ); $template = 'Profession {"is":strtoupper} {profession_name:strtoupper:lcfirst}. [{total_found}, {total_found} vacancies found, No vacancies found]. {profession_name} in your town'; $pattern = <<<'EOD' ~ (?=[[{]) # speed up the pattern by quickly skipping all characters that are not # a "[" or a "{" without to test the two branches of the alternation (?: # conditional \[ { (?<if> [^}]+ ) } , (?<then> [^][,]* ) (?:, (?<else> [^][]* ) )? ] | # basic replacement (?<!\[) # allow nested conditionals { (?<var_name> [^{}:]+ ) (?: : (?<func_name> [^{}:]+ ) )? # first function to apply (?: (?<other_funcs> : [^}]+ ) )? # allow to chain functions } ) ~x EOD; $replacement = function ($m) use ($registry, $available_functions) { if (!empty($m['if'])) { $cond = $m['if']; # when the condition doesn't exist, the string is evaluated as it if (isset($registry[$cond])) $cond = $registry[$cond]; return $cond ? $m['then'] : $m['else']; } else { $value = isset($registry[$m['var_name']]) ? $registry[$m['var_name']] : trim($m['var_name'], '"\''); if (isset($m['func_name'])) { $func = trim($m['func_name']); if (in_array($func, $available_functions)) $value = call_user_func($func, $value); } if (isset($m['other_funcs'])) return '{\'' . $value . '\'' . $m['other_funcs'] . '}'; return $value; } }; $result = $template; do { $result = preg_replace_callback($pattern, $replacement, $result, -1, $count); } while ($count); echo $result; 

When the condition is met, the approach is to replace first with a good branch and continue the replacement within the branch for the second time. This is why preg_replace_callback is in a do...while . Another reason is to allow chain functions.

Please note that, with the exception of small improvements in speed and readability, the template does not need to use special functions.

I added several improvements, such as the default behavior (when something is not found in the registry), the ability to use chains and literals. You can obviously change them to your feet according to your needs.

+1
source

All Articles