0

わかりました、これが悪い習慣であることはわかっていますが、コードの一部が既存のものであり、1 つの引数でカスタム関数を実行するように拡張する必要があります。

したがって、ページはデータベースに保存され、テンプレートに表示されるとき、現在、html ページ全体で e 修飾子を使用して 3 つの異なる preg_replace 関数を使用しています。

これは遅いように見えるので、1 つの preg_replace 呼び出しのみを使用するように変更し、bbcode の方法で 1 つの引数を持つカスタム関数を提供できるようにしたいと思います: 例:

[FUNC:testfunc(テスト文字列)]

それで、これが私が思いついたものです...どの方法がより安全かはわかりません.e修飾子を持つpreg_rplace、または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() 関数が記事クラス全体に渡され、使用できるようになります。試合ごとにこのような無名関数を作成するのは、パフォーマンス的に悪いですか?

4

1 に答える 1

1

これを実行する回数によっては、匿名関数の作成が悪い場合があります。

次のように、いつでもコールバックのメソッド呼び出しを使用できます。

$content = preg_replace_callback($rx, array($obj, 'method_name'), $content);

これにより、引数が既にオブジェクト プロパティである場合に、引数をメソッドに渡す必要がなくなります。

preg_replace_callback()私は 'e'を好む傾向がありますpreg_replace()。これは、eval されたコード内のパターン マッチを正しくエスケープするという落とし穴を回避し、eval のオーバーヘッドをまったく回避できるからです (また、APC のようなオペコード キャッシュを使用している場合は、これは、すべての呼び出しでコンパイルされる評価に対してコンパイルがゼロであることを意味します)。また、コードが少し読みやすくなります。文字列をエスケープする必要があるため、eval されたコードは常に少し醜く見えます。

そうは言っても、「e」で preg_replace() を使用することに本質的に問題はありません。

于 2011-10-19T03:42:31.090 に答える