7

カスタム フレームワーク用に開発しているイベント システムのアイデアがあります。

このような疑似関数を想像してください。

class Test
{
    public function hi()
    {
        Event::add(__FUNCTION__ . 'is about to run.');
        return "hi";
    }
}

さらにいくつかの関数に対して同じことを行う必要があると想像してください。(実行時に実行された関数をログに記録し、それらを別のファイルに記録したい場合があります。)

これを行ってイベントを手動で関数に追加する代わりに、このようなことを行うことはできますか?

class Test
{
    public function hi()
    {
        return "hi";
    }
}

// events.php (It's a pseudo code so may not work.)
// Imagine extend's purpose is to inject codes into target function

Event::bind('on', $className, $methodName, function() use ($className, $methodName) 
{
    return $className->$methodName->extend('before', Event::add(__FUNCTION__ . 'is about to run.'));
});

アイデアは、hi()内部にある関数を注入し、外部から関数Test classに渡すものを注入することです。は、注入がターゲット関数の最初の行にある必要があることを意味します。extend'before'

最後に、イベントとイベント バインディングは関数から完全に抽象化された状態に保たれます。関数を変更せずにカスタムのものをバインドできるようにしたい。

eval()をハッキングしたり、いじったりすることで、これを行うことができると思いますcall_user_func()。よくわかりませんが。使用eval()はすでにかなり悪い音です。

私の質問は;

  1. PHPでできることはありますか?
  2. OOP/OOP Principles に名前があるので、さらに読むことができますか?
  3. それは意味がありますか、それとも悪い考えですか?
4

1 に答える 1

2

はい、できます。GO!を使用してAOPを使用できます。注釈で動作するAOP フレームワーク。

たとえば、すべてのパブリック メソッドの呼び出しをログに記録したいとします。このようにすべての関数行に追加する代わりに。

namespace Acme;

class Controller
{
    public function updateData($arg1, $arg2)
    {
        $this->logger->info("Executing method " . __METHOD__, func_get_args()); 
        // ...
    }    
}

次のように、Acme 名前空間のすべてのクラスのすべてのパブリック メソッドに対して1 つのアスペクトを使用できます。

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;

    class LoggingAspect implements Aspect
    {
        /** @var null|LoggerInterface */
        protected $logger = null;

        /** ... */
        public function __construct($logger) 
        {
            $this->logger = $logger;
        }

        /**
         * Method that should be called before real method
         *
         * @param MethodInvocation $invocation Invocation
         * @Before("execution(public Acme\*->*())")
         */
        public function beforeMethodExecution(MethodInvocation $invocation)
        {
            $obj    = $invocation->getThis();
            $class  = is_object($obj) ? get_class($obj) : $obj;
            $type   = $invocation->getMethod()->isStatic() ? '::' : '->';
            $name   = $invocation->getMethod()->getName();
            $method = $class . $type . $name;

            $this->logger->info("Executing method " . $method, $invocation->getArguments());
        }
    }    

より複雑に見えますが、より柔軟です。

于 2013-05-20T00:49:26.947 に答える