简体   繁体   中英

How to autowire an entity into a service?

I have an abstract class called AbstractMediaService and a some specific implementations of this abstract 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';
    }
}

These objects require a Media entity to work with

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
{}

Controller

/**
 * @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
}

Problem is that I need some dependencies like the Security service or the EntityManager .

I would like to know how autowire AbstractMediaService service.

This is wrong. You cannot autowire Media to be injected into a service, because entities are not services .

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

If VideoMediaService and PhotoMediaService (I renamed them for clarity, since sharing the name with your entity made it look like it were related) need an instance of Media to perform some work, just make that a parameter for the corresponding methods.

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

Or alternatively, simply have a setMedia(Media $media) method on that class for that:

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

Frankly, this latter approach does not seem like a great idea. You would need to make the methods that work on $media aware of the possibility of setMedia() not having been called yet, or subsequent calls to setMedia() would change how the service behaved. Just making it a parameter of the appropriate method is much cleaner, clearer and safer.

Injecting those services is done like any other service. That they extend an abstract class is irrelevant.

/**
 * @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');
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM