首页 > 解决方案 > Symfony 和 Api-Platform:在控制器之外使用 Doctrine 和其他服务

问题描述

你好 Stackoverflow

我们遇到了 Symfony 和 API-PLATFORM 的问题。我们尝试了很多东西,但找不到任何解决方案。我们在使用 stackoverflow 上已经给出的答案以及他们遇到的与此问题相关的 git 问题时遇到了困难。这就是为什么这不是任何形式的重复,因为那些遗憾地没有帮助我们。

问题如下。我们src的 api-platform 文件夹中有标准结构。

- 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 EntityManager?我们尝试使用默认的 AbstractController 进行扩展,但这不正确且不起作用。

当我们想使用我们的安全类来获取当前用户时,也会发生同样的事情。( $this->security->getUser())。即使我们像使用一样导入它。use Symfony\Component\Security\Core\Security;.

我们希望我们对这个问题很清楚。我们有点绝望,因为几天后我们仍在寻找解决方案。我们使用 PHP 版本7.1.3和 API-PLATFORM 版本1.1(composer.json)

编辑1:不存在是关于未定义的方法(getDoctrine)。我们尝试了一些方法来实现这一点。例如使用 AbstractController 来扩展类。另一个有效的解决方案是通过函数传递 DoctrineManager。然而,这不是一个好的做法。

编辑 2:请求的 AuthController 片段。它显示了我们如何使用电话实用程序。是不是我需要在围绕以下代码的这个函数中实现 EntityInterface?

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

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

标签: symfony

解决方案


实体管理器可以使用依赖注入(DI)模式来处理。这种模式完全集成在 Symfony 中。这就是 Symfony 的有趣和神奇之处。

所有实现接口的类都可以通过依赖注入获得。使用 Symfony4+,自动配置被激活。这似乎很复杂,但对于最终的开发人员来说,这很容易。这是一个使用您的电话类执行此操作的简单示例,这似乎是您实现业务逻辑的模型。

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 管理器。只需用 EntityManagerInterface 或 Phone utils 类替换 swiftmailer。

(在控制器中,它存在一种最简单的方法来检索电话实用程序类)

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

如果您想获得一个自动装配的类(如安全层),您可以这样做。要查找可以自动装配的类,有一些提示:

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

它将返回与您的搜索相对应的所有类。

(如果你不使用 symfony 可执行文件,你可以用 php bin/console debug:autowiring 替换它)


推荐阅读