2015-10-14 94 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 –

相關問題