2

教育目的で PHP フレームワークを開発しています。私はそれを始めて以来、多くのことを学びました。

依存関係をどのように処理するかを決定しました。私は単純な DI コンテナーを作成しています。


の最初の質問は、DI コンテナー自体についてではなく、外部 (DI コンテナーの前) で作成されたオブジェクトを注入する方法です。

Q:例: 私は を呼び出してcontainer->manualAdd('_logger', $logger);います。これを達成する別の方法はありますか?DI コンテナーのアイデアを壊していますか?


2 番目の質問は、関数のフックについてです。そのため、ブートストラップですべてのオブジェクトがインスタンス化されると、オブジェクト自体が機能し始めることができます。

Q:例: EventDispatcher を作成しています。doneBuildまたはのいずれかで何かをする必要がある人は誰でもbeforeTerminate、 が注入されBootstrapEventDispatcherます。これを行う別の方法はありますか?

EventDispatcher私はやり過ぎだと思い始めbootstrap、おそらく次のようなものを実装します: CodeIgniter:Hooks

どんな助けでも大歓迎です。

ブートストラップの例 (疑似コード):

function bootstrap($file = 'file.xml'){
    $logger = new Logger();
    $logger->log('bootstrap: init');

    $dispatcher = new BootstrapEventDispatcher($logger);

    $container = new DIContainer(new ConfigReader($file), $logger);
    $container->manualAdd('_logger', $logger);
    $container->manualAdd('_bootstrap_event_dispatcher', $dispatcher);
    $container->build();
    $dispatcher->doneBuild(null, new EventArgs());

    $dispatcher->beforeTerminate(null, new EventArgs());
    $logger->log('bootstrap: terminate');
}
class DIContainer{
    public function build(){
        //read xmls and create classes, etc.
        $this->logger->log('DIContainer: creating objects: {objects}');
    }
}

XML の例:

<!-- example file.xml !-->
<services>
    <service id="simple_class" class="SimpleClass"></service>
    <service id="complex_class" class="ComplexClass">
        <argument type="service" id="simple_class" /> <!-- dependency injection !-->
        <argument type="service" id="_logger" /> <!-- dependency injection !-->
        <argument type="service" id="_bootstrap_event_dispatcher" /> <!-- dependency injection !-->
    </service>
</services>

ComplexClass の例:

class ComplexClass{
    public function __construct(SimpleClass $simpleClass, BootstrapEventDispatcher $dispatcher, Logger $logger){
        $this->simpleClass = $simpleClass;
        $this->logger = $logger;
        $dispatcher->onDoneBuild(array($this, 'onBootstrapDoneBuild'));
    }
    public function onBootstrapDoneBuild($obj, $args){
        //do something.
        $this->logger->log('complexclass: did something');
    }
}
4

1 に答える 1

2

私の Silex/Symfony2 での理解から、この種のことを行うための「魔法のような方法」は存在しないということです。

私の最初の質問: コンテナーの前に作成されたオブジェクトを追加することは許可されています。

Symfony2 では、Kernel:initializeContainer関数内でカーネルがコンテナーに追加され ( $this->container->set('kernel', $this);)、後で xml ファイルでサービスがカーネルと共に注入されます ( <argument id="kernel" type="service" />)。

Silex では、Application:__construct関数によってオブジェクトが作成され、コンテナーに追加されます。Applicationに自分自身を注入するServiceProvidersため、これらのプロバイダーはオブジェクトに依存関係を注入し、それらをコンテナーに追加できます。

$container->manualAdd('_logger', $logger); 正しいです。


私の2番目の質問については、それをどのように処理したいかによって異なります。私は3つのオプションを思いつきました:

.1 C# のイベントのようKernelに、コンテナーに追加されます。

ComplexClass では:kernel.terminate += kernelTerminate

.2EventDispatcher EventDispatcher (クラスが xml ファイルで作成される依存関係を必要としない限り)

//bootstrap function:
$dispatcher = new KernelEventDispatcher();
$kernel = new Kernel($dispatcher);
$container->manualAdd('_kernel.dispatcher');

.

<!-- in file.xml:ComplexClass !-->
<argument id="_kernel.dispatcher" type="service" />

.3インターフェイスを実装するオブジェクトを作成します: (別の名前が見つかりませんでしたRunnable)

<!-- in file.xml !-->
<service id="complex_class_runnable" class="ComplexClassRunnable">
    <argument type="service" id="complex_class" />
    <argument type="service" id="_kernel" />
</service>

.

//in ComplexClassRunnable
$kernel->addRunnable($this);

.

//in Kernel
foreach($this->runnables as $runnable){
    $runnable->init(); //same for terminate
}

ブートストラップが更新されました:

function bootstrap($file = 'file.xml'){
    $logger = new Logger();
    $logger->log('bootstrap: init');

    $kernel = new Kernel($logger);
    $container = new DIContainer(new ConfigReader($file), $logger);

    $container->manualAdd('_kernel', $kernel);
    $container->manualAdd('_logger', $logger);
    $container->build();

    $kernel->boot();

    $logger->log('bootstrap: terminate');
}
class DIContainer{
    public function build(){
        //read xmls and create classes, etc.
        $this->logger->log('DIContainer: creating objects: {objects}');
    }
}
class Kernel{
    public function boot(){
        //...
    }
}
于 2013-06-06T20:34:18.913 に答える