6

要するに私の質問: 複数のコントローラーに単一のファクトリーを使用できますか?

詳細:

/config/autoload/global.phpには、次のようなグローバルな非モジュール固有の設定がいくつかあります。

return array(
    'settings' => array(
        'setting_a' => 'foo',
        'setting_b' => 'bar'
    ),

    // More ZF default configuration ...
);

ここで、常に呼び出すことなく、すべてのコントローラーでこれらの設定にアクセスできるようにしたいと考えて$this->getServiceLocator()->get('config')います。

したがって、私の考えは、構成配列に注入されるクラス属性$settingsを myに導入することでした。AbstractControllerのコンストラクターで構成を直接取得しようとしましたAbstractController。ただしgetServiceLocator()、その時点では準備ができていないようで、NULL を返します。

すべてのコントローラーのコントローラー ファクトリを構築し、次のように設定を挿入できます。

class ControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator) {
        $config = $serviceLocator->get('config');
        return new \MyModule\Controller\MyController($config['settings']);
    }
}

しかし、それは何度も何度も同じでしょう。私の質問は、複数のコントローラーに単一のファクトリーを使用できますか?

私のmodule.config.phpでは、複数のコントローラに対して 1 つのファクトリ クラスを指定できます。

return array(
    'controllers' => array(
        'factories' => array(
            'MyModule\Controller\MyControllerA' => 'MyModule\Factory\ControllerFactory',
            'MyModule\Controller\MyControllerB' => 'MyModule\Factory\ControllerFactory',
            'MyModule\Controller\MyControllerC' => 'MyModule\Factory\ControllerFactory',
        )
    ),
);

しかし、ファクトリでは、実際の Controller オブジェクトを手動で返す必要があります (上記の例を参照)。もちろん、これは Controller ごとに 1 つの Factory でのみ機能します。

希望、私は私の問題を明確にしました。

更新 2013 年 3 月 24 日:

私は最初にイニシャライザを作成することで提案された解決策に従いましたが、構成の注入のためだけにそれを使用することは決して好きではありませんでした。

それで、私は掘り下げ続け、設定を受け取るためのコントローラープラグインを作成することになりました。

プラグインのコードは次のようになります。

use Zend\Mvc\Controller\Plugin\AbstractPlugin;

class Settings extends AbstractPlugin
{
    protected $settings;

    public function __invoke()
    {
        $config = $this->getController()->getServiceLocator()->get('Config');

        if (isset($config['settings']) && is_array($config['settings'])) {
            $this->settings = $config['settings'];
        }

        return $this->settings;
    }
}

module.config.phpにプラグインを追加した後

'controller_plugins' => array(
    'invokables' => array(
        'settings' => 'My\Controller\Plugin\Settings',
    )
),

を呼び出すだけで、コントローラー内の設定に簡単にアクセスできます$this->settings()。これが誰にも役立つことを願っています。

4

3 に答える 3

6

イニシャライザーをアタッチしてみると、コントローラーが作成されるときに、インスタンスが既知のイニシャライザーと照合されます。インスタンスが特定のインターフェースまたは抽象クラスに一致する場合は、いくつかの共通論理を適用できます。

私はこのアプローチをコントローラーでテストしていませんが、ControllerLoaderがServiceManager / ServiceLocatorの一種であるため、理論的には機能するはずです。

'controllers' => array (
    'initializers' => array(
        'MyApplication\Controller\Initializer'
    )
),

その場合、Initalizerは次のようになります。

class Initializer implements InitializerInterface
{
    public function initialize($instance, ServiceLocatorInterface $serviceLocator)
    {
        if (!$instance instanceof MyControllerInterface)
        {
            return;
        }

        // Do something for this instance
    }
}
于 2012-10-22T10:05:09.870 に答える
1

またはさらにクリーン:コントローラーを呼び出し可能として構成に追加してから、コントローラーをワンライナーに変える次のような操作を行います。

abstract class AbstractControllerFactory implements FactoryInterface
{
    protected $controllerKey;

    public function createService(ServiceLocatorInterface $serviceLocator) {
        $config     = $serviceLocator->get('config');
        $controller = $serviceLocator->get($this->controllerKey);
        $controller->setConfig($config);
        return $controller;
    }
}

class ControllerFactory extends AbstractControllerFactory implements FactoryInterface
{
    protected $controllerKey = 'mymodule_controller_mycontroller';
}
于 2013-02-28T15:32:53.533 に答える
1

将来の更新「UPDATE 2013-03-24」をどのように行ったかわかりません;)

あなたが提案したようにコントローラを使用するだけではなく、すべてのコントローラに必要なコードを抽象ファクトリに入れてから継承するのはなぜですか。次に例を示します。

abstract class AbstractControllerFactory implements FactoryInterface
{
    protected function initialise(ServiceLocatorInterface $serviceLocator, $controller) {
        $config = $serviceLocator->get('config');
        $controller->setConfig($config);
    }
}

class ControllerFactory extends AbstractControllerFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator) {
        $controller = new \MyModule\Controller\MyController();
        $this->initialise($serviceLocator, $controller);
        return $controller;
    }
}
于 2013-02-28T15:29:26.343 に答える