1

私はmodule.config.phpファイルに非共有サービスとコントローラファクトリを作成するファクトリを持っています。コンフィギュレーションのこの部分は次のようになります。ZendFramework2にServiceLocatorを注入しないで複数の非共有インスタンスを作成するには?

"service_manager" => [ 
    "factories" => [ 
     Entity\User::class => Factory\Entity\UserFactory::class 
    ], 
    "shared" => [ 
     Entity\User::class => false 
    ] 
], 
"controllers" => [ 
    "factories" => [ 
     Controller\UserAdminController::class => Factory\Controller\UserAdminControllerFactory::class 
    ] 
] 

私はので、私はUserエンティティクラスの複数のインスタンスをインスタンス化する必要があり、管理者は、同時に複数のユーザーを追加することができますので、ユーザエンティティは、非共有であります。

<?php 

namespace User\Factory\Controller\Core; 

use User\Controller\UserAdminController; 
use Interop\Container\ContainerInterface; 
use User\Entity\User; 
use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 

class UserAdminControllerFactory implements FactoryInterface{ 

    /** 
    * @param ContainerInterface $container 
    * @param string $requestedName 
    * @param array|null $options 
    * 
    * @return UserAdminController 
    */ 
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null){ 
     $serviceLocator = $container->getServiceLocator(); 

     return new UserAdminController($serviceLocator->get(User::class)); 
    } 

    /** 
    * @param ServiceLocatorInterface $serviceLocator 
    * 
    * @return UserAdminController 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator){ 
     return $this($serviceLocator, UserAdminController::class); 
    } 

} 

現在のところ、それはコントローラのコンストラクタ内のUserエンティティクラスの単一インスタンスのみを注入:

は、ここに私のコントローラの工場です。しかし、管理者が何を望んでいるかに基づいて、未定義の新しいインスタンスが必要です。

可能な解決策の1つは、コントローラ内で$this->getServiceLocator()->get(User::class)を呼び出すことによって、サービスロケータ全体を渡して新しいインスタンスを作成することですが、これはアンチパターンとみなされます。

ここでの質問は、UserFactoryクラスを使用して、コントローラでユーザーの新しいインスタンスを作成する方法です。

EDIT1:UserFactoryを追加します。

<?php 

namespace User\Factory\Entity\Core; 

use User\Entity\User; 
use Interop\Container\ContainerInterface; 
use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 

class UserFactory implements FactoryInterface{ 

    /** 
    * @param ContainerInterface $container 
    * @param string $requestedName 
    * @param array|null $options 
    * 
    * @return User 
    */ 
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null){ 
     $urlHelper = $container->get("ViewHelperManager")->get("url"); 

     return new User($urlHelper); 
    } 

    /** 
    * @param ServiceLocatorInterface $serviceLocator 
    * 
    * @return User 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator){ 
     return $this($serviceLocator, User::class); 
    } 

} 
+0

ここにあなたが見ているものhttp://stackoverflow.com/questions/25447442/dependency-injection-in-factories?rq=1 私はよく分かりませんが、工場にコントローラを挿入してユーザーエンティティ – bxN5

+0

UserFactoryのコンテンツも共有できますか?ドメインエンティティ用のファクトリを作成する強い理由はありますか?とにかく、私はそのようなタスクのコントローラプラグインを作成しようとします。 – edigu

+0

@Roman私は私の工場でサービスロケータが必要なので、私は工場を注入する場合、私は同様にアンチパターンであるサービスロケータを注入する必要があります。したがって、私はこれを行うことはできません。何か案は? – thexpand

答えて

0

最善のアプローチは、コントローラにUserエンティティの新しいインスタンスを注入することです。コントローラの工場は次のようになります。ユーザーの新しいインスタンスが必要とされているコントローラ、内部

<?php 

namespace User\Factory\Controller\Core; 

use User\Controller\UserAdminController; 
use Interop\Container\ContainerInterface; 
use User\Entity\User; 
use Zend\ServiceManager\FactoryInterface; 
use Zend\ServiceManager\ServiceLocatorInterface; 

class UserAdminControllerFactory implements FactoryInterface{ 

    /** 
    * @param ContainerInterface $container 
    * @param string $requestedName 
    * @param array|null $options 
    * 
    * @return UserAdminController 
    */ 
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null){ 
     $serviceLocator = $container->getServiceLocator(); 

     return new UserAdminController($serviceLocator->get(User::class)); 
    } 

    /** 
    * @param ServiceLocatorInterface $serviceLocator 
    * 
    * @return UserAdminController 
    */ 
    public function createService(ServiceLocatorInterface $serviceLocator){ 
     return $this($serviceLocator, UserAdminController::class); 
    } 

} 

を、それは単にPHPのクローン機能を呼び出すことによって作成することができます。ここでそれを行う方法のコントローラの例アクションです:工場出荷時は、Userクラスの新しいインスタンスを作成するために、サービスロケータを使用しているため、コントローラにUserFactoryを注入

<?php 

namespace User\Controller\Core; 

use User\Entity\User; 
use Zend\View\Model\ViewModel; 
use Zend\Mvc\Controller\AbstractActionController; 

class UserAdminController extends AbstractActionController { 

    /** 
    * @var User 
    */ 
    public $user; 

    /** 
    * @param User $user 
    */ 
    public function __construct(User $user){ 
     $this->user = $user; 
    } 
    /** 
    * @return ViewModel 
    */ 
    public function indexAction(){ 
     if($this->getRequest()->isPost()){ 
      $usersData = $this->params()->fromPost("usersData"); 
      foreach($usersData as $userData){ 
       $newUser = clone $this->user; 
       $newUser->fromArray($userData); 
       $newUser->save(); 
      } 
     } 

     return ViewModel(); 
    } 

} 

は、ませオプションです。もし工場がコントローラに注入されているのであれば、サービスロケータも注入されるべきですが、これはアンチパターンとみなされ、さらにZendFramework3では非推奨であり、悪い習慣とみなされます。

関連する問題