Symfony и Api-Platform: использование Doctrine и других сервисов вне контроллеров - PullRequest
1 голос
/ 14 апреля 2020

Hello Stackoverflow

У нас проблема с Symfony и API-PLATFORM. Мы много чего перепробовали, но не нашли решения. У нас возникли трудности с использованием ответов, уже предоставленных для stackoverflow, и с проблемами git, которые у них связаны с этим вопросом. Вот почему это не дубликат в любой форме, поскольку, к сожалению, они не помогли нам.

Проблема заключается в следующем. У нас есть стандартная структура в нашей папке src на API-платформе.

- src
-- Annotation
-- Controller
-- Doctrine
-- Emails
-- Entity
-- EventListener
-- EventSubscriber
-- Filters
-- Repository
-- Security
-- Utils

Итак, вот с чего начинается наша проблема. У нас есть несколько классов, которые являются лишь некоторыми утилитами для удобного использования. Они находятся в папке utils. Этот вопрос касается класса в папке Utils с именем Phone. (пространство имен App\Utils\Phone). Дело в том, что нам нужно использовать EntityManager в этом классе Utils, потому что нам нужно хранить некоторые данные (временно). Мы сделаем это с помощью следующего кода (который работает в контроллерах)

$em = $this->getDoctrine()->getManager();
$em->persist($smsStore);
$em->flush();

Теперь появляется ошибка: Doctrine здесь даже не существует. Это не может быть найдено. Здесь возникает вопрос: как мы можем использовать Doctrine EntityManager вне контроллеров? Мы попытались расширить с помощью установленного по умолчанию AbstractController, но это не может быть правильным и не работает.

То же самое происходит, когда мы хотим использовать наш класс безопасности для получения текущего пользователя. ($this->security->getUser()). Даже когда мы импортируем это как с использованием. use Symfony\Component\Security\Core\Security;.

Мы надеемся, что с этим вопросом все прояснилось. Мы немного в отчаянии, потому что мы все еще ищем решение через несколько дней. Мы используем PHP версию 7.1.3 и версию API-PLATFORM 1.1 (composer. json)

РЕДАКТИРОВАТЬ 1: Не существует о неопределенном методе (получить Doctrine). Мы попробовали несколько вещей, чтобы реализовать это. Например, используя AbstractController для расширения класса. Другое решение, которое сработало, - это передача DoctrineManager вместе с функцией. Однако это не очень хорошая практика.

РЕДАКТИРОВАТЬ 2: Фрагмент AuthController в соответствии с запросом. Это показывает, как мы используем Phone Utils. Может быть, мне нужно реализовать EntityInterface в этой функции, окружающей следующий код?

    $phone = new Phone();
    $phone->overwriteUser($this->getUser());

    $phone->newRecipient("4917640733908");
    $phone->setBody("Hello, this is a test.");

1 Ответ

1 голос
/ 14 апреля 2020

Менеджер сущностей может обрабатываться с помощью шаблона внедрения зависимостей (DI). Этот шаблон полностью интегрирован в Symfony. Это забавный и волшебный c аспект Symfony.

Все классы, реализующие интерфейс, доступны с внедрением зависимостей. С Symfony4 + автоконфигурация активирована. Это кажется сложным, но для конечного разработчика это довольно просто. Вот простой пример того, как сделать это с вашими классами Phone, которые, кажется, представляют собой модель, в которой вы реализовали свою бизнес-логику c.

class Phone
{
    private $entityManager;

    //The entity manager will be provided to your constructor with the dependency injection.
    public function __construct(EntityManagerInterface $entityManager)
    {
       $this->entityManager = $entityManager;
    }

    public function save($smsStore)
    {
       //you own logic go here

       //here is the magic part, the entityManager is available, connected, ready to use. 
       $this->entityManager->persist($smsStore);
       $em->flush();
    }
}

Когда вы будете вызывать метод классов Utils, DI создаст его автоматически, и вы сможете использовать его свойство, в данном случае менеджер сущностей.

Если вы хотите использовать свой класс в контроллере, вы можете сделать это, добавив класс телефона в его конструктор :

class AuthController extends AbstractController
{
    public function __construct(Phone $phoneUtils)
    {      
       $this->phoneUtils = $phoneUtils;
    }

    public function someAction()
    {
       //your own logic here

       //here is the magic part, the phone Utils is ready, it imports the entitymanager
       //when you want to save your smsStore, simply call it
       $this->phoneUtils->save($smsStore);
    }
}

Вы используете Api-Platform, нет проблем! Вы можете воспроизвести этот шаблон проектирования в других классах, таких как ваши DataPersisters или в ваших EventListeners. Если вы посмотрите на этот пример в документации ApiPlateform , вы увидите, как автор получает менеджер Swiftmailer в своем прослушивателе событий. Просто замените swiftmailer на EntityManagerInterface или классы использования телефона.

(В контроллере существует самый простой способ извлечь класс использования телефона)

class AuthController extends AbstractController
{
    //Do That: ADD Phone $phoneUtils as an argument in the method
    public function someAction(Phone $phoneUtils)
    {
       //your own logic here
       //Do not do that: $phoneUtils = new Phone();

       //Magic! when you want to save your smsStore, simply call it
       $phoneUtils->save($smsStore);
    }
}

Если вы хотите получить Класс autowired (например, уровень безопасности), вы можете сделать это. Чтобы найти, какие классы могут быть подключены автоматически, есть несколько советов:

symfony console debug:autowiring
symfony console debug:autowiring Security
symfony console debug:autowiring AuthorizationChecker

. Он вернет все классы, соответствующие вашему запросу.

(Если вы не используете исполняемый файл symfony , вы можете заменить его на php bin / console debug: autowiring)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...