好的,我知道这是一个不好的做法,但部分代码是存在的,我必须扩展它以使用一个参数运行自定义函数。
因此,我们的页面存储在数据库中,当它们显示在我们的模板中时,我们目前在整个html页面上使用三个不同的preg_replace函数和e修饰符。
这看起来很慢,所以我想将它更改为只使用一个preg_replace调用,并且能够以bbcode方式提供带有1个参数的自定义函数:示例:
[FUNC:testfunc(test string)]
所以,这就是我想出来的......我不确定哪种方法更安全,preg_rplace与e modifer或preg_replace_callback:
<?php
$str = '
<h2>Title That should Not Be Affected</h2>
<p>[FUNC:linkbox(/somestuff/newpage.html)]</p>
<a href="[FUNC:getvar(url)]">[FUNC:getvar(title)]</a>
<p>Random Html THat should not be affected</p>
<p>[FUNC:linkbox(/somestuff/otherpage.html)]</p>
';
$str2 = preg_replace_callback('~\[FUNC:(.*?)\((.*?)\)\]~', 'callback_caller', $str);
$str = preg_replace('~\[FUNC:(.*?)\((.*?)\)\]~e', 'emodcaller("\\1", "\\2")', $str);
echo $str.'<br><br>'.$str2;
function callback_caller($args){
if(!isset($args[0], $args[1]))
return false;
$func = strip_tags($args[1]);
$param = isset($args[2]) ? strip_tags($args[2]) : '';
//Only allow calling of known functions
switch($func){
case 'linkbox':
return linkbox($param);
break;
case 'getvar':
return getvar($param);
break;
case 'default':
return '';
break;
}
}
function emodcaller($fun, $arg){
$arg = strip_tags($arg);
//Only allow calling of known functions
switch($fun){
case 'linkbox':
return linkbox($arg);
break;
case 'getvar':
return getvar($arg);
break;
case 'default':
return '';
break;
}
}
function linkbox($addy){
return 'Linkbox Called: '.$addy;
}
function getvar($arg) {
switch($arg){
case 'url':
return '/index.html';
break;
case 'title':
return 'This is a test title';
break;
}
}
?>
我喜欢使用e修饰符的方法是,如果需要的话,我可以直接在php中将另一个参数添加到函数调用中,如下所示:
preg_replace('~\[FUNC:(.*?)\((.*?)\)\]~e', 'emodcaller("\\1", "\\2", $page->getid())', $str);
一种方法比另一种方法更安全吗?它们都是巨大的安全风险吗?我必须要实现这些......
编辑:我发现你可以使用匿名函数传递回调函数附加参数,如:
$content = preg_replace_callback(
'~(?:\<p\>)?\[FUNC:(.*?)\((.*?)\)\](?:\<\/p\>)?~',
function($matches) use ($article) {
return callback_caller($matches, $article);
},
$content);
这会将callback_caller()函数传递给我整个文章类以供使用。 是否为每一场比赛创建了一个像这样的匿名函数,性能方面呢?
答案 0 :(得分:1)
根据您执行此操作的次数,创建匿名函数可能不好。
您始终可以使用方法调用进行回调,如下所示:
$content = preg_replace_callback($rx, array($obj, 'method_name'), $content);
如果它们已经是对象属性,那么可以避免将任何参数传递给方法。
我倾向于preg_replace_callback()
优于preg_replace()
和'e',因为它避免了在eval'd代码中正确转义任何模式匹配的缺陷,并避免了必须进行eval的开销(如果你正在使用像APC这样的操作码缓存,那就意味着编译零与每次调用编译的eval相比)。它还使代码更容易阅读 - eval'd代码总是看起来有点丑陋,因为你必须逃避字符串。
也就是说,使用preg_replace()与'e'没有任何内在错误。