我正在尝试实施一个管理界面,管理员可以在其中创建网站元标记形成的高级规则。
我有一个函数,它接受一个模板并用$ registry中的值替换其中的占位符,并在需要时应用修饰符。
$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);
示例:
专业{name:ucfirtst}是{profession_name:strtoupper}
分为
专业名称是ACTOR
我正在尝试实施条件,因此可以制定这样的规则:
在条件之前使用{placeholdes}的文字。 [{total_found},带有{占位符}的TRUE文本,带有{占位符}的FALSE文本],带有{占位符}的条件后跟踪文本。
所以我的函数会从注册表中得到{total_found}值,并且如果它是true或false则会返回带有相应false或true-pattern的字符串。 我在正则表达式上非常糟糕,并且无法弄清楚如何用正则表达式来编写这个条件。 请帮帮我。
更新: 具体的例子看起来像威尔:
$template = 'Profession is {profession_name}. [{total_found}, {total_found} vacancies found, No vacancies found]. {profession_name} in your town';
在我的回调函数中,我会放置一个像这样的条件
if ($matches[condition]) // i don't no how exactly
$result = $matches[true-condition];
else
$result = $matches[false-condition]
所以,如果$registry['total_found'] = 100;
最终结果将是«职业是演员。找到100个职位空缺。你镇上的演员»。
如果$registry['total_found'] = 0;
最终结果将是«职业是演员。没有找到空缺。你镇上的演员»。
答案 0 :(得分:1)
$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;
当满足条件时,方法包括首先替换好分支并在第二次进行分支内部的替换。这就是preg_replace_callback
在do...while
循环中的原因。另一个原因是允许链接函数。
请注意,除了速度和可读性的小改进外,该模式不需要使用特殊功能。
我添加了一些改进,例如默认行为(当在注册表中找不到某些内容时),使用链式函数和文字字符串的能力。显然,你可以根据需要改变它们。