Я поставил еще один вопрос, пытаясь найти способ статического доступа к классу репозитория вне контроллера в пользовательском классе «помощник».
Пока единственный способ, которым я понял, как это сделать, – использовать приведенный ниже код. Если кто-то хочет перезвонить в другой вопрос о «лучшей практике» или «шаблонах дизайна», пожалуйста, сделайте это.
Я открыл этот вопрос, чтобы найти наилучший метод использования однопользовательской службы (?), Загружаемой при загрузке 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; } }
Рад видеть, что ты больше не бегаешь.
Ваш подход не будет работать, если кто-то сначала не выгрузит репозиторий из контейнера, поэтому инициализируется self :: $ instance. Но вы действительно не хотите это делать. Супер хаки.
Вы хотите ввести службу репозитория в ваш слушатель ядра. Попытка заставить репозиторий действовать как слушатель ядра – это не очень хороший дизайн. Поэтому просто сделайте сервис для своего репозитория, а затем второй для слушателя. Вначале это может показаться немного странным, но на практике это действительно хорошо работает, и именно так разработан 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; }
Плохой дизайн, но по крайней мере он избавляется от взлома слушателя, и он избегает создания репозитория, пока он не понадобится. Это также означает, что вы можете получить доступ к репозиторию из команд (слушатели не настраиваются при вызове команд).
Я не понимаю, какая прибыль будет в этом методе. Идея 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; }