#symfony #doctrine
#php #symfony #доктрина #symfony5
Вопрос:
Как указывает моя среда разработки, этот AbstractController::getDoctrine()
метод теперь устарел.
Я не нашел никаких ссылок на это устаревание ни в официальной документации, ни в списке изменений Github.
Какова новая альтернатива или обходной путь для этого ярлыка?
Ответ №1:
Как упоминалось здесь:
Вместо того, чтобы использовать эти ярлыки, внедрите соответствующие службы в методы конструктора или контроллера.
Вам нужно использовать внедрение зависимостей.
Для данного контроллера просто введите ManagerRegistry
конструктор контроллера.
use DoctrinePersistenceManagerRegistry;
class SomeController {
public function __construct(private ManagerRegistry $doctrine) {}
public function someAction(Request $request) {
// access Doctrine
$this->doctrine;
}
}
Комментарии:
1. Могу ли я спросить, в чем разница между EntityManagerInterface и ManagerRegistry и почему последний вариант лучше?
2. Я не знаю, «лучше» ли это. Это просто эквивалентно старому поведению
getDoctrine()
. Также можно внедритьEntityManagerInterface
. Посмотрите, что работает лучше для вас, в зависимости от ваших потребностей. Проверьте, что предоставляет каждый сервис.3.
ManagerRegistry
позволяет извлекатьEntityManagerInterface
менеджеры, отличные от стандартных, если вы их используете. Если у вас только один менеджер, внедрение EntityManagerInterface подойдет. Проверьте исходный код для обоих интерфейсов, чтобы увидеть, в чем разница. Например, вы не можете сохранять или удалять напрямую, используяManagerRegistry
объект. Вы должны сделать это через объект, созданныйManagerRegistry::getManager()
. В конце концов, не имеет большого значения, какой из них вы выберете. Выберите менее подробный или лучше подходящий для вашего варианта использования.
Ответ №2:
Вы можете использовать EntityManagerInterface $EntityManager:
public function delete(Request $request, Test $test, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete'.$test->getId(), $request->request->get('_token'))) {
$entityManager->remove($test);
$entityManager->flush();
}
return $this->redirectToRoute('test_index', [], Response::HTTP_SEE_OTHER);
}
Ответ №3:
Согласно ответу @yivi и, как указано в документации, вы также можете следовать приведенному ниже примеру, вводя DoctrinePersistenceManagerRegistry
непосредственно в нужный вам метод:
// src/Controller/ProductController.php
namespace AppController;
// ...
use AppEntityProduct;
use DoctrinePersistenceManagerRegistry;
use SymfonyComponentHttpFoundationResponse;
class ProductController extends AbstractController
{
/**
* @Route("/product", name="create_product")
*/
public function createProduct(ManagerRegistry $doctrine): Response
{
$entityManager = $doctrine->getManager();
$product = new Product();
$product->setName('Keyboard');
$product->setPrice(1999);
$product->setDescription('Ergonomic and stylish!');
// tell Doctrine you want to (eventually) save the Product (no queries yet)
$entityManager->persist($product);
// actually executes the queries (i.e. the INSERT query)
$entityManager->flush();
return new Response('Saved new product with id '.$product->getId());
}
}
Ответ №4:
В моем случае полагаться на автоматическую проводку на основе конструктора или метода недостаточно гибко.
У меня есть черта, используемая рядом контроллеров, которые определяют свою собственную автоматическую проводку. Функция предоставляет метод, который извлекает некоторые числа из базы данных. Я не хотел жестко связывать функциональность функции с настройкой автоматического подключения контроллера.
Я создал еще одну черту, которую я могу включить в любое место, где мне нужно получить доступ к Doctrine. Бонусная часть? Это все еще законный подход к автоматической проводке:
<?php
namespace AppController;
use DoctrinePersistenceManagerRegistry;
use DoctrinePersistenceObjectManager;
use SymfonyContractsServiceAttributeRequired;
trait EntityManagerTrait
{
protected readonly ManagerRegistry $managerRegistry;
#[Required]
public function setManagerRegistry(ManagerRegistry $managerRegistry): void
{
// @phpstan-ignore-next-line PHPStan complains that the readonly property is assigned outside of the constructor.
$this->managerRegistry = $managerRegistry;
}
protected function getDoctrine(?string $name = null, ?string $forClass = null): ObjectManager
{
if ($forClass) {
return $this->managerRegistry->getManagerForClass($forClass);
}
return $this->managerRegistry->getManager($name);
}
}
и затем
<?php
namespace AppController;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use AppEntityFoobar;
class SomeController extends AbstractController
{
use EntityManagerTrait
public function someAction()
{
$result = $this->getDoctrine()->getRepository(Foobar::class)->doSomething();
// ...
}
}
Если у вас есть несколько менеджеров, как у меня, вы также можете использовать getDoctrine()
аргументы для выбора нужного.