1

クラスのイベント ハンドラーを作成していますが、コードの評価ではなくクロージャーを使用した方がよいのではないかと考えていました。

eval() を使用する唯一の理由は、クラス内のすべてにアクセスできるからです (そして、本当に安全ではありません:D) が、クロージャがアクセスできるかどうかはわかりません。

私がこのようなことをした場合:

<?php
    class SomethingCool {
        protected $handlers;

        public function addHandler($cmd, closure $func) {
            $this->handlers[$cmd][] = $func;
        }

        public function handle($cmd) {
            if(!isset($this->handlers[$cmd]))
                return false;
            foreach($this->handlers[$cmd] as $func)
                $func();
        }
    }
?>

<?php
    $wut = new SomethingCool();
    $wut->addHandler('lol', function() use($wut) {
                                $wut->handle('lol');
                            }
                    );
?>

エラーなしで実行されますか? 私はそれを自分でテストしますが、現時点ではできません。

4

2 に答える 2

2

を使用してハンドラーを作成するevalと、次のようなコードを作成することになります。

$wut->addHandler('lol', '$this->handle(\'lol\');');

引用符のエスケープとエディターでの壊れた構文の強調表示に関する明らかにひどい問題とは別に、これにより、あいまいな依存関係の問題が発生します。$thisあなたのコードでは何を参照していますか? コードのように文字通り機能するのではなく、特定のコンテキスト内で評価されることに依存します。これにより、コードは本当に混乱します。

別の方法は、依存性注入です。

$wut->addHandler('lol', function (SomethingCool $sc) {
    $sc->handle('lol');
});

このハンドラーを呼び出すSomethingCoolと、関数の引数として自分自身を挿入します。それははるかに堅牢です。これは、このコールバックを他のコンテキストに渡して、バックグラウンドで必要なことを実行できることを意味します。コールバックは、特定のコンテキスト内で評価されることに依存しなくなりました。

または、クロージャーを使用します。

$wut->addHandler('lol', function () use ($wut) {
    $wut->handle('lol');
});

これには、依存関係がどこから来ているのかを確認し、依存できることを知っているという同じ利点があります。

そうです、もよりも優れていevalます。

于 2012-12-10T17:34:17.663 に答える
0

あなたのインスタンスSomethingCoolを各ハンドラーに渡さないのはなぜですか?

public function handle($cmd) 
{
    if (!isset($this->handlers[$cmd])) {
        return;
    }
    foreach ($this->handlers[$cmd] as $func)
        $func($this); // pass ourself to each handler
    }
}

$wut->addHandler('lol', function(SomethingCool $obj) {
    // $obj refers to the SomethingCool instance
});

$wut->handle('lol');

ところで、ハンドラーも削除できるようにしたい場合はSplObjectStorage、各コマンド カテゴリを使用することもできます。

于 2012-12-10T17:32:48.797 に答える