【问题标题】:symfony2 and run service automaticallysymfony2 并自动运行服务
【发布时间】:2014-01-20 10:15:32
【问题描述】:

我决定在 symfony2.4 中创建一个服务,它可以访问我项目中所有范围内的容器。

所以我创建了一个模型:

namespace Nevec\RaxcidoBundle\Model;

class Base {
    public static $container;

    public function __construct() {
        self::$container = $container;
    }


}

并在 resources/config/services.yml 中将此模型设置为服务

parameters:
    nevec_raxcido.core: Nevec\RaxcidoBundle\Model\Base

services:
    nevec_raxcido.example:
        class: %nevec_raxcido.core%
        arguments: [@service_container]

现在,如您所知,我应该像这样在控制器中调用此服务:

$this->get("nevec_raxcido.example");

但我想自动加载此服务,而不在控制器中调用上述命令

问题是如何在 symfony2 内核启动后自动加载服务?

【问题讨论】:

  • 您想达到什么目标?您的服务目标是什么?
  • 我想访问我在模型文件夹中创建的自定义模型中的容器和学说:$container = Model\Base::$container;
  • 您正在尝试使服务容器成为全局对象。这将引导您进行许多良好的练习休息。真的 - 你不需要这个..
  • 您可以将容器注入到您想要的服务中。但更好的方法是直接注入特定的服务(而不是整个容器)。
  • 好的,好主意,我只是将原则发送到我的服务,但是如何自动调用服务?我不想在我所有的控制器中都调用它!!!

标签: php symfony frameworks containers


【解决方案1】:

我找到了解决方案,看来我们应该在 services.yml 中使用监听器,例如:

parameters:
    nevec_raxcido.core: Nevec\RaxcidoBundle\Model\Base

services:
    nevec_raxcido.example:
        class: %nevec_raxcido.core%
        arguments: [@service_container]
        tags:
            - {name: kernel.event_listener, event: kernel.request, method: onKernelRequest}

还有这个模型:

<?php
namespace Nevec\RaxcidoBundle\Model;

class Base{
    public static $container;

    public function __construct($container) {

        self::$container = $container;
    }

    public function onKernelRequest($event){
        return;
    }

}

这样您就可以在应用程序的所有范围内访问容器:

$container = Model\Base::$container;

【讨论】:

    【解决方案2】:

    请不要使用服务容器。使用依赖注入。

    class Service {
        private $service;
    
        public function __construct(SomeServiceInterface $someService){
            $this -> service = $service;
        }
    }
    

    和 yml:

    services:
        service1:
            class: SOMENAMESPACE\Service
            arguments: [@service2]
        service2:
            class: SOMENAMESPACE\SomeService
    

    现在您可以访问 SOMENAMESPACE\Service 中的 SOMENAMESPACE\SomeService。您可以通过以下方式在控制器中获取服务:

    $this -> get('service1');
    

    假设学说是您要注入的具体服务。

    这样做:

    class Service {
        private $em;
    
        protected function getEm(ObjectManager $em){
            $this -> em = $em;
        }
    }
    
    services:
        service1:
            class: SOMENAMESPACE\Service
            arguments: [@doctrine.orm.entity_manager]
    

    问题的第二部分:如何自动加载?挺容易。构建一个“BaseController”并扩展它。

    class BaseAppController extends Controller{
        private $service;
    
        protected function getService(){
            if (!($this -> service instanceof SomeServiceInterface)) $this -> service = $this -> get('service');
            return $this -> service;
        }
    }
    

    通过 $this 访问 -> getService()

    【讨论】:

    • 你的答案的第二部分不能这样工作...... ContainerAware 类,如扩展 Controller 的类通过 setter injection 接收服务容器(又名。对setContainer(...) 的调用在对象创建之后 注入容器)...$this-&gt;get(..) 在 ContainerAware 类的构造函数中是不可能的,因为它将尝试访问此时未设置$this-&gt;container 属性!
    • 好的,从来没有尝试过。感谢您的回复。 kernel.event.listener 呢?它可以指向某个函数。容器以前建过吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多