Symfony2-Как использовать доступ к службе из-за пределов контроллера

В моем контроллере Symfony2 это отлично работает:

$uploadManager = $this->get('upload.upload_manager');

, но когда я перехожу к пользовательскому прослушивателю:

use Doctrine\ORM\Event\LifecycleEventArgs;
use Acme\UploadBundle\Upload\UploadManager;

class PersonChange
{
    public function postRemove(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $entityManager = $args->getEntityManager();

        $uploadManager = $this->get('ep_upload.upload_manager');
        echo "the upload dir is " . $uploadManager->getUploadDir();
    }
}

Я получаю сообщение об ошибке:

Fatal error: Call to undefined method Acme\MainBundle\Listener\PersonChange::get() in /home/frank/...

Я знаю, что мне нужно использовать инструкцию, но не знаю, что использовать.

Ответы

Ответ 1

Обновление: определение контроллеров как служб больше не рекомендуется в Symfony.

Метод get() в классе Controller - это просто вспомогательный метод для получения сервисов из контейнера, и он должен был ускорить работу новых разработчиков Symfony2. Как только люди получают удовольствие от внедрения структуры и зависимостей, рекомендуется определить контроллеры как службы и явно ввести каждую требуемую услугу.

Поскольку ваш класс PersonChange не является контроллером и не расширяет класс Controller, у вас нет вспомогательного метода get(). Вместо этого вам необходимо определить свой класс как услугу и явно ввести нужные службы. Подробнее читайте Раздел Контейнера.

Ответ 2

Как я столкнулся с одной и той же проблемой, может быть, я могу помочь

То, что сказал Эльнур, прекрасно, и я просто попытаюсь найти пример реальной жизни.

В моем случае я хотел получить доступ к

$lucenemanager = $this->get('ivory.lucene.manager')

Даже при расширении контроллера я не мог заставить его работать, пока контроллер действительно получает доступ к контейнеру (я все еще не понял почему)

В config.yml мой слушатель (searchindexer.listener) объявлен следующим образом:

   services:
    searchindexer.listener:
        class: ripr\WfBundle\Listener\SearchIndexer
        arguments:
              luceneSearch: "@ivory_lucene_search"
        tags:
            - { name: doctrine.event_listener, event: postPersist }

Служба (ivory.lucene.search) передается в качестве аргумента в моем сервисе/слушателе.

Тогда в моем классе

protected $lucenemanager;

        public function __construct($luceneSearch)
        {
            $this->lucenemanager = $luceneSearch;
        }

Затем вы можете использовать метод get для $this

Ответ 3

Подход, который всегда работает, несмотря на то, что он не является лучшей практикой в ​​OO

global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');‏

Ответ 4

Если вам нужно получить доступ к Сервису, определите его в конструкторе класса:

class PersonChange{
    protected $uploadManager;
    public function __construct(UploadManager $uploadManager){
        $this->uploadManager = $uploadManager;
    }
    // Now you can use $this->uploadManager.
}

Теперь вы можете передать аргумент Service как аргумент при вызове класса (пример 1) или определить сам клас как службу ( рекомендуется, пример 2)

Пример 1:

use Acme\PersonChange;
class appController{
    function buzzAction(){
        $uploadManager = $this->get('upload.upload_manager');
        $personChange = new PersonChange($uploadManager);

Пример 2 (лучше):

Определите PersonChange как саму службу и определите другую Службу как аргумент в файле services.yml:

 # app/config/services.yml
services:
    upload.upload_manager:
        class:     AppBundle\uploadManager

    PersonChange:
        class:     AppBundle\PersonChange
        arguments: ['@upload.upload_manager']

Таким образом, вам не нужно беспокоиться о службе upload_manager в контроллере, поскольку она неявно передается в качестве аргумента для конструктора, поэтому ваш контроллер может быть:

class appController{
    function buzzAction(){
        $personChange = $this->get('PersonChange');