【问题标题】:Best way to use ServiceManager in Model Class?在模型类中使用 ServiceManager 的最佳方式?
【发布时间】:2023-03-05 01:41:01
【问题描述】:

我正在尝试在我的实体类上使用 Service Manager,但我不知道最好的方法。

在控制器上很容易,因为我们可以使用以下命令调用服务管理器:$this->getServiceLocator();

但是,在我的实体类中,即使我实现了 ServiceLocatorAwareInterface,我也可以检索 ServiceManager,因为我的实体类没有被服务管理器调用:

那么最好的方法是什么:

1 - 从我的控制器传递我的实体类中的 serviceManager 2 - 使用 ServiceManager 构建我的实体类 3 - ... ?

为了更好地理解我的问题,这是我的代码不起作用:

我的实体类:

class Demande extends ArraySerializable implements InputFilterAwareInterface {
/../
    public function getUserTable() {
    if (! $this->userTable) {

        $sm = $this->getServiceLocator();//<== doesn't work !
        $this->userTable = $sm->get ( 'Application\Model\UserTable' );
    }
    return $this->userTable;
}

【问题讨论】:

    标签: zend-framework2


    【解决方案1】:

    我不会将 ServiceManager 注入您的模型(尽管您可以)。我宁愿让 ServiceManager 为您构建模型,并将您需要的任何内容直接注入模型中。

    服务配置:

    'factories' => array(
        'SomethingHere' => function($sm) {
            $model= new \My\Model\Something();
    
            return $model;
        },
        '\My\Model\Demande' => function($sm) {
            $model= new \My\Model\Demande();
            /**
             * Here you use the SM to inject any dependencies you need
             * into your model / service what ever..
             */
            $model->setSomething($sm->get('SomethingHere'));
    
            return $model;
        },
        /**
         * Alternatively you can provide a class implementing
         * Zend\ServiceManager\FactoryInterface
         * which will provide an instance for you instad of using closures
         */
        '\My\Model\DemandeDefault' => '\My\Model\DemandeFactory',
    

    将您的任何依赖项放在服务管理器配置中,然后使用它为您将任何依赖项注入您的模型、服务等。

    如果您想使用工厂方法而不是闭包,请提供一个示例工厂类:

    DemandeFactory.php

    use Zend\ServiceManager\FactoryInterface;
    use Zend\ServiceManager\ServiceLocatorInterface;
    
    class DemandeFactory implements FactoryInterface
    {
        /**
         * Create a new Instance
         *
         * @param ServiceLocatorInterface $serviceLocator
         * @return Demande
         */
        public function createService(ServiceLocatorInterface $serviceLocator)
        {
            $config = $serviceLocator->get('Config'); // if you need the config..
            // inject dependencies via contrustor
            $model = new \My\Model\Demande($serviceLocator->get('SomethingHere'));
            // or using setter if you wish.
            //$model->setSomething($serviceLocator->get('SomethingHere'));
    
            return $model;
        }
    }
    

    您尝试通过服务管理器实例化的示例模型。

    需求.php

    class Demande
    {
        protected $_something;
    
        /**
         * You can optionally inject your dependancies via your constructor
         */
        public function __construct($something)
        {
            $this->setSomething($something);
        }
    
        /**
         * Inject your dependencies via Setters
         */
        public function setSomething($something)
        {
            $this->_something = $something;
        }
    
        // Something will be injected for you by the Service Manager
        // so there's no need to inject the SM itself.
    }
    

    在您的控制器中:

    public function getDemande() 
    {
        if (! $this->_demande) {
            $sm = $this->getServiceLocator();
            $this->_demande = $sm->get ('\My\Model\Demande');
        }
        return $this->_demande;  
    }  
    

    您可以将 SergiceManager/ServiceLocator 注入您的模型,但您的模型将依赖于 ServiceLocator。

    【讨论】:

    • 非常有用的答案!不将 ServiceManager 注入模型的另一个原因是通过这种方式我们无法序列化我们的对象(因为 ServiceManager 上的闭包)。因此我们无法在会话中保存模型。
    • 我觉得唯一需要补充的是你不应该过度使用Closures。改为编写工厂类。这将提高整体性能,因为类只会按需实例化。所有闭包都将在每个请求上实例化。
    • 还有一点:如果某些依赖项是绝对必需的,强烈建议使用__construct()or injection 而不是Setter-Injection
    • 很好的补充,不过我会写一整天来提供所有的可能性和优化,这样你就可以在一个更容易学习的地方看到你的所有部门 ;-)
    • 为您更新了示例工厂和构造函数注入:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-23
    • 1970-01-01
    相关资源
    最近更新 更多