Symfony 5.4及更高版本中getDoctrine()的新替代方法

3yhwsihp  于 2022-11-16  发布在  其他
关注(0)|答案(5)|浏览(216)

正如我的IDE所指出的,AbstractController::getDoctrine()方法现在已被弃用。
我在官方文档和Github的修改日志中都没有找到任何关于这个反对的参考。
此快捷方式的新替代方法或解决方法是什么?

aelbi1ox

aelbi1ox1#

如上所述here
不要使用这些快捷方式,而是在构造函数或控制器方法中注入相关服务。
您需要使用依赖注入。
对于给定的控制器,只需在控制器的构造函数上注入ManagerRegistry

use Doctrine\Persistence\ManagerRegistry;

class SomeController {

    public function __construct(private ManagerRegistry $doctrine) {}

    public function someAction(Request $request) {
        // access Doctrine
        $this->doctrine;
    }
}
hl0ma9xz

hl0ma9xz2#

您可以使用实体管理器接口$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);
}
ljsrvy3e

ljsrvy3e3#

根据@yivi的回答和文档中提到的,您也可以按照下面的示例,直接在所需的方法中注入Doctrine\Persistence\ManagerRegistry

// src/Controller/ProductController.php
namespace App\Controller;

// ...
use App\Entity\Product;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Response;

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());
    }
}
rqcrx0a6

rqcrx0a64#

在控制器中添加代码,不改变控制器逻辑

<?php
//...
use Doctrine\Persistence\ManagerRegistry;
//...
class AlsoController extends AbstractController
{
    public static function getSubscribedServices(): array
    {
        return array_merge(parent::getSubscribedServices(), [
            'doctrine' => '?'.ManagerRegistry::class,
        ]);
    }
    protected function getDoctrine(): ManagerRegistry
    {
        if (!$this->container->has('doctrine')) {
            throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".');
        }
        return $this->container->get('doctrine');
    }
...
}

阅读更多https://symfony.com/doc/current/service_container/service_subscribers_locators.html#including-services

7rfyedvj

7rfyedvj5#

在我的例子中,依赖于基于构造函数或方法的自动配置不够灵活。
我有一个trait,很多Controller都使用它来定义自己的自动配置。这个trait提供了一个从数据库中获取一些数字的方法。我不想把trait的功能和controller的自动配置设置紧密结合起来。
我创造了另一个特征,我可以在任何需要访问教义的地方添加它。额外的好处是?它仍然是一个合法的自动安装方法:

<?php

namespace App\Controller;

use Doctrine\Persistence\ManagerRegistry;
use Doctrine\Persistence\ObjectManager;
use Symfony\Contracts\Service\Attribute\Required;

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 App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use App\Entity\Foobar;

class SomeController extends AbstractController
{
    use EntityManagerTrait

    public function someAction()
    {
        $result = $this->getDoctrine()->getRepository(Foobar::class)->doSomething();
        // ...
    }
}

如果您像我一样有多个管理器,也可以使用getDoctrine()参数来获取正确的管理器。

相关问题