2015-10-14 1 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 :: $ instance. Но вы действительно не хотите это делать. Супер хаки.

Вы хотите инсталлировать службу репозитория в ваш слушатель ядра. Попытка заставить репозиторий действовать как слушатель ядра - это не очень хороший дизайн. Поэтому просто сделайте сервис для своего репозитория, а затем второй для слушателя. Вначале это может показаться немного странным, но на практике это действительно хорошо работает, и именно так разработан S2.

Если по какой-то причине вы придерживаетесь понятия, что вы должны иметь доступ к контейнеру по всему миру, тогда имейте в виду, что ваше ядро ​​определено глобально (посмотрите на app.php), и у него есть метод getContainer в Это.

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

Но опять же не должно быть необходимости в этом.

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

Update - Похоже, что вы пытаетесь использовать слушатель функциональность только для настройки одиночных чисел.Вы должны стараться избегать одиночек, но если вы действительно думаете, что вы нуждаетесь в них, то можно использовать глобальный доступ к ядру:

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

Не могли бы вы немного подробнее проинформировать службу репо в прослушиватель ядра? Вы говорите, что я делаю хорошо, но я должен вводить один слушатель ядра, а не каждый репо, являющийся слушателем ядра (например, мой примерный код выше)? – 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 –

Смежные вопросы