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');