如何将实体自动装配到服务中?

How to autowire an entity into a service?

我有一个名为 AbstractMediaService 的抽象 class 和这个抽象的一些特定实现 class:

abstract class AbstractMediaService
{
    private $em;
    private $media;
    public function __construct(EntityManagerInterface $em, Media $media)
    {
        $this->em = $em;
        $this->media = $media;
    }

    public function dosomethingInCommon();
    abstract public function dosomethingSpecific();
}

class PhotoMediaService extends AbstractMediaService
{
    public function dosomethingSpecific()
    {
        echo 'i am a photo service';
    }
}

class VideoMediaService extends AbstractMedia
{
    public function dosomethingSpecific()
    {
        echo 'i am a video service';
    }
}

这些对象需要 Media 实体才能使用

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;

class Media
{}

控制器

/**
 * @Route("/{_locale}/infos/{idMedia}.html", name="info", methods={"GET"}, requirements={
 *   "idMedia" = "\d+",
 * })
 */
public function infosPhotoAction(RequestStack $requestStack, Media $media)
{
   $request = $requestStack->getCurrentRequest();
   $session = $requestStack->getSession();

   $media = new PhotoMedia($media);

   // return response
}

问题是我需要一些依赖项,例如 Security 服务或 EntityManager

我想知道如何自动装配 AbstractMediaService 服务。

这是错误的。您不能自动装配 Media 以注入到服务中,因为 实体不是服务

public function __construct(EntityManagerInterface $em, Media $media)

如果 VideoMediaServicePhotoMediaService(为了清楚起见,我重命名了它们,因为与您的实体共享名称使其看起来像是相关的)需要 Media 的实例来执行一些工作,只需将其作为相应方法的参数即可。

public function dosomethingInCommon(Media $media);
abstract public function dosomethingSpecific(Media $media);

或者,只需在 class 上使用 setMedia(Media $media) 方法即可:

public function setMedia(Media $media) {
    $this->media = $media;
}

坦率地说,后一种方法似乎不是一个好主意。您需要让在 $media 上工作的方法意识到 setMedia() 尚未被调用的可能性,否则对 setMedia() 的后续调用将改变服务的行为方式。将其作为适当方法的参数会更干净、更清晰、更安全。

注入这些服务的方式与其他任何服务一样。他们扩展抽象 class 是无关紧要的。

/**
 * @Route("/{_locale}/infos/{idMedia}.html", name="info", methods= {"GET"}, requirements={
 *   "idMedia" = "\d+",
 * })
 */
public function infosPhotoAction(RequestStack $requestStack, Media $media, PhotoMediaService $photoMediaService): Response
{
    $request = $requestStack->getCurrentRequest();
    $session = $requestStack->getSession();

    $photoMediaService->doSomethingSpecific($media)
     
    return new Response('all done');
}