2015-10-14 50 views
0

我发布了另一个question试图找到一种方法来静态访问自定义“帮助”类中的控制器外的存储库类。Syfmony - 启动加载服务

到目前为止,我已经想出了如何实现这一点的唯一方法是使用下面的代码。如果有人想要谈谈关于“最佳实践”或“设计模式”的其他问题,请做。

我打开这个问题,寻求在symfony启动时加载单例服务(?)以便其他类可以静态访问它,而无需任何依赖注入的最佳方法。我找不到任何官方文档或常见做法。我知道单身人士是反实践,但方法是最好的方法,还是有更理想的解决方案?

services.yml

parameters: 
    entity.device: Asterisk\DbBundle\Entity\Device 
services: 
    asterisk.repository.device: 
    class: Asterisk\DbBundle\Entity\Repositories\DeviceRepository 
    factory: ["@doctrine.orm.asterisk_entity_manager", getRepository] 
    arguments: 
     - %entity.device% 
    tags: 
     - {name: kernel.event_listener, event: kernel.request, method: onKernelRequest} 

DeviceRepository

class DeviceRepository extends \Doctrine\ORM\EntityRepository 
{ 
    /** @var ExtendedEntityRepository */ 
    protected static $instance; 

    public function __construct(EntityManager $entityManager, ClassMetadata $class) 
    { 
     parent::__construct($entityManager, $class); 

     if(static::$instance instanceof static == false) 
      static::$instance = $this; 
    } 

    public static function getInstance() 
    { 
     return static::$instance; 
    } 

    public function onKernelRequest($event) 
    { 
     return; 
    } 
} 

回答

1

很高兴看到你不再跑来跑去。

除非有人先将容器从容器中抓取出来,否则您的方法无法工作,所以self :: $实例被初始化。但是你真的不想这样做。超级哈克。

您希望将存储库服务注入内核侦听器。试图使存储库充当内核监听器并不是一个好设计。因此,只需为您的存储库提供服务,然后再为听众提供服务。起初看起来有点奇怪,但它在实践中确实很好地工作,而且是S2设计的方式。

如果由于某种原因,你坚持必须能够全局访问容器的概念,那么请注意,你的内核是全局定义的(看一下app.php),它有一个getContainer方法它。

$repo = $_GLOBAL['kernel']->getContainer()->get('asterisk.repository.device'); 

但是,应该没有必要这样做。

==============================

更新 - 它看起来像你试图使用监听器功能只是设置单身人士。你应该尽量避免单身,但如果你真的认为你需要他们,然后到内核的全球访问可以用于:

class DeviceRepository extends \Doctrine\ORM\EntityRepository 
{ 
    /** @var ExtendedEntityRepository */ 
    protected static $instance; 

    public static function getInstance() 
    { 
    if (!static::$instance) { 
     static::$instance = $_GLOBAL['kernel']->getContainer()->get('asterisk.repository.device'); 
    } 
    return static::$instance; 
    } 

不好的设计,但至少它得到的摆脱听者的破解,它避免了在创建资源库直到实际需要为止。这同样意味着你可以从命令访问存储库(当命令被调用时,监听器没有设置)。

+0

能详细介绍一下将repo服务注入内核侦听器吗?你在说我在做什么很好,但我应该注入一个内核侦听器,而不是每个作为内核侦听器的repo(就像我上面的示例代码)? – StrikeForceZero

+0

您是否正在使用侦听器功能来设置存储库单例实例? – Cerad

+0

是的,因为我知道没有其他方式可以在symfony靴子时加载它 – StrikeForceZero

0

我不明白的利润将这个方法是什么。 servicecontainer的思想是只为每个类创建一个实例,并为请求使用相同实例的任何方法提供引用(或指针,如果你喜欢)。让我来证明它:

服务定义:

// app/config.yml 
services: 
    app.test: 
     class: Vendor\AppBundle\Service\Test 

和自定义类:

// src/AppBundle/Service/Test.php 
namespace AppBundle/Service; 

class Test { 
    public $test = 0; 
} 

和控制器:

// src/AppBundle/Controller/DefaultController 
namespace AppBundle/Controller; 

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Request; 

class DefaultController extends Controller 
{ 
    /** 
    * @Route("/", name="homepage") 
    */ 
    public function indexAction() 
    { 
     $instance1 = $this->get('app.test'); 
     $instance2 = $this->get('app.test'); 

     $instance1->test = 1; 

     echo $instance2->test; // RETURNS 1 !!! 
     exit; 
    } 
+0

正确:但如果您需要访问控制器外的服务(请参阅其他问题链接)我需要能够调用控制器外的Test :: someMethod() – StrikeForceZero

+0

http://stackoverflow.com/questions/12056178/how-to-access-service-container-in-symfony2-global-helper-function-service –

相关问题