Symfony에서 저장소에 주입하려면 어떻게 해야 합니까?
나는두개의물체를 주입해야 합니다에 두 개체 도입해야 합니다.ImageService
그 중 하나가바로 그 예다. 그들 중 하나는 인스턴스.Repository/ImageRepository
저는 이런면:이런생각이 듭니다.
$image_repository = $container->get('doctrine.odm.mongodb')
->getRepository('MycompanyMainBundle:Image');
그럼 서비스에서는 어떻게 선언해야 하나요?yml?서비스는 다음과 같습니다.
namespace Mycompany\MainBundle\Service\Image;
use Doctrine\ODM\MongoDB\DocumentRepository;
class ImageManager {
private $manipulator;
private $repository;
public function __construct(ImageManipulatorInterface $manipulator, DocumentRepository $repository) {
$this->manipulator = $manipulator;
$this->repository = $repository;
}
public function findAll() {
return $this->repository->findAll();
}
public function createThumbnail(ImageInterface $image) {
return $this->manipulator->resize($image->source(), 300, 200);
}
}
다음은 저처럼 구글에서 온 사람들을 위한 정리된 솔루션입니다.
업데이트: Symfony 2.6(이상) 솔루션은 다음과 같습니다.
services:
myrepository:
class: Doctrine\ORM\EntityRepository
factory: ["@doctrine.orm.entity_manager", getRepository]
arguments:
- MyBundle\Entity\MyClass
myservice:
class: MyBundle\Service\MyService
arguments:
- "@myrepository"
권장되지 않는 솔루션(Symfony 2.5 이하):
services:
myrepository:
class: Doctrine\ORM\EntityRepository
factory_service: doctrine.orm.entity_manager
factory_method: getRepository
arguments:
- MyBundle\Entity\MyClass
myservice:
class: MyBundle\Service\MyService
arguments:
- "@myrepository"
이 링크를 찾았는데, 이 링크를 사용할 수 있었습니다.
parameters:
image_repository.class: Mycompany\MainBundle\Repository\ImageRepository
image_repository.factory_argument: 'MycompanyMainBundle:Image'
image_manager.class: Mycompany\MainBundle\Service\Image\ImageManager
image_manipulator.class: Mycompany\MainBundle\Service\Image\ImageManipulator
services:
image_manager:
class: %image_manager.class%
arguments:
- @image_manipulator
- @image_repository
image_repository:
class: %image_repository.class%
factory_service: doctrine.odm.mongodb
factory_method: getRepository
arguments:
- %image_repository.factory_argument%
image_manipulator:
class: %image_manipulator.class%
경우에 만약는 서비스로 버전에서 버전부터 시작하여 각 저장소를 서비스로 정의하지 않는 경우부터 각 저장소를 정의하고 싶지 않다.2.4
당신은,(다음을 수행할 수 있습니다 다음과 같이 할 수 있다.default
회사 매니저의 이름):.A엔티티매니저의 이름입니다 cm이다.
@=service('doctrine.orm.default_entity_manager').getRepository('MycompanyMainBundle:Image')
Symfony 3.3, 4 및 5는 이를 훨씬 단순하게 합니다.
보다 일반적인 설명은 Symfony에서 서비스로서의 독트린을 사용한 저장소 사용 방법을 참조하십시오.
코드에 따르면 SOLID 패턴 중 하나인 상속 위에 컴포지션을 사용하면 됩니다.
1.독트린에 직접 의존하지 않고 자체 저장소 만들기
<?php
namespace MycompanyMainBundle\Repository;
use Doctrine\ORM\EntityManagerInterface;
use MycompanyMainBundle\Entity\Image;
class ImageRepository
{
private $repository;
public function __construct(EntityManagerInterface $entityManager)
{
$this->repository = $entityManager->getRepository(Image::class);
}
// add desired methods here
public function findAll()
{
return $this->repository->findAll();
}
}
2. PSR-4 기반의 자동 등록에 의한 구성 등록 추가
# app/config/services.yml
services:
_defaults:
autowire: true
MycompanyMainBundle\:
resource: ../../src/MycompanyMainBundle
3. 이제 컨스트럭터 주입을 통해 모든 종속성을 추가할 수 있습니다.
use MycompanyMainBundle\Repository\ImageRepository;
class ImageService
{
public function __construct(ImageRepository $imageRepository)
{
$this->imageRepository = $imageRepository;
}
}
제 경우 @Tomash Votruba의 답변에 기초하고 있으며, 이 질문은 다음과 같은 접근방식을 제안합니다.
어댑터 어프로치
상속 없음
범용 어댑터 클래스 만들기:
namespace AppBundle\Services; use Doctrine\ORM\EntityManagerInterface; class RepositoryServiceAdapter { private $repository=null; /** * @param EntityManagerInterface the Doctrine entity Manager * @param String $entityName The name of the entity that we will retrieve the repository */ public function __construct(EntityManagerInterface $entityManager,$entityName) { $this->repository=$entityManager->getRepository($entityName) } public function __call($name,$arguments) { if(empty($arrguments)){ //No arguments has been passed $this->repository->$name(); } else { //@todo: figure out how to pass the parameters $this->repository->$name(...$argument); } } }
그런 다음 foreach entity 예를 들어 서비스를 정의합니다(예를 들어 php를 사용하여 symfony 서비스를 정의합니다).
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine'),AppBundle\Entity\ContactEmail::class]);
상속과 함께
위의 순서 1과 동일
그 확장을 확장하다.
RepositoryServiceAdapter
예를 들어 수업예를들어 다음과 같습니다.namespace AppBundle\Service\Adapters; use Doctrine\ORM\EntityManagerInterface; use AppBundle\Entity\ContactEmail; class ContactEmailRepositoryServiceAdapter extends RepositoryServiceAdapter { public function __construct(EntityManagerInterface $entityManager) { parent::__construct($entityManager,ContactEmail::class); } }
서비스 등록:
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine')]);
어느 경우든 테스트 가능한 방법으로 데이터베이스를 테스트하는 것이 좋습니다.또, 그 방법에 대해 크게 걱정할 필요 없이, 서비스를 유닛으로 테스트하고 싶은 경우에 대해서도, 조롱하는 것이 도움이 됩니다.예를 들어 다음과 같은 서비스가 있다고 가정합니다.
//Namespace definitions etc etc
class MyDummyService
{
public function __construct(RepositoryServiceAdapter $adapter)
{
//Do stuff
}
}
Repository Service Adapter는 다음 저장소를 채택합니다.
//Namespace definitions etc etc
class SomeRepository extends \Doctrine\ORM\EntityRepository
{
public function search($params)
{
//Search Logic
}
}
테스트
그래서 너는 쉽게 법 따라서 메서드의 동작을 쉽게 조롱/하드코드/에뮬레이트할 수 있습니다의 행동 mock/hardcode/emulate 수 있다.search
에 정의되어 있다에 정의된 것이다.SomeRepository
을 조롱하는 것에 의해 aither은 어느 쪽도 조롱이든RepositoryServiceAdapter
non-inheritance 접근 또는비준거성 접근법 또는에서.ContactEmailRepositoryServiceAdapter
상속에서는.상속받은것 중 하나.
팩토리 어프로치
또는 다음 팩토리를 정의할 수도 있습니다.
namespace AppBundle\ServiceFactories;
use Doctrine\ORM\EntityManagerInterface;
class RepositoryFactory
{
/**
* @param EntityManagerInterface $entityManager The doctrine entity Manager
* @param String $entityName The name of the entity
* @return Class
*/
public static function repositoryAsAService(EntityManagerInterface $entityManager,$entityName)
{
return $entityManager->getRepository($entityName);
}
}
그런 다음 다음을 수행하여 php 서비스 주석으로 전환합니다.
「」에 격납해 주세요../app/config/services.php
(symfony v3.4의 경우,.
putject의 루트로 간주됩니다.)
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
$definition = new Definition();
$definition->setAutowired(true)->setAutoconfigured(true)->setPublic(false);
// $this is a reference to the current loader
$this->registerClasses($definition, 'AppBundle\\', '../../src/AppBundle/*', '../../src/AppBundle/{Entity,Repository,Tests,Interfaces,Services/Adapters/RepositoryServiceAdapter.php}');
$definition->addTag('controller.service_arguments');
$this->registerClasses($definition, 'AppBundle\\Controller\\', '../../src/AppBundle/Controller/*');
그리고,./app/config/config.yml
(.
putject의 루트로 간주됩니다.)
imports:
- { resource: parameters.yml }
- { resource: security.yml }
#Replace services.yml to services.php
- { resource: services.php }
#Other Configuration
그런 다음 다음과 같이 서비스를 정리할 수 있습니다(이 예에서는 Dummy 엔티티 이름에서 사용).Item
):
$container->register(ItemRepository::class,ItemRepository::class)
->setFactory([new Reference(RepositoryFactory::class),'repositoryAsAService'])
->setArguments(['$entityManager'=>new Reference('doctrine.orm.entity_manager'),'$entityName'=>Item::class]);
일반적인 힌트로서 전환하기 위해서php
service annotation을 사용하면 위의 고급 서비스 구성 씬을 문제 없이 수행할 수 있습니다.코드 스니펫의 경우는, 를 사용해 작성한 특별한 저장소를 사용합니다.factory
방법.
Symfony 5의 경우 services.yml이 없어도 의존관계를 주입할 수 있습니다.
- 서비스 컨스트럭터에 엔티티 매니저 삽입
private $em; public function __construct(EntityManagerInterface $em) { $this->em = $em; }
- 다음으로 저장소를 가져옵니다.
$this->em->getRepository(ClassName: 클래스)
ClassName을 엔티티 이름으로 바꿉니다.
언급URL : https://stackoverflow.com/questions/12223176/how-to-inject-a-repository-into-a-service-in-symfony
'programing' 카테고리의 다른 글
JavaScript에서 바이트 단위의 크기를 KB, MB, GB로 변환하는 올바른 방법 (0) | 2022.10.11 |
---|---|
Rxandroid SubscribeOn과 ObservateOn의 차이점은 무엇입니까? (0) | 2022.10.11 |
Joomla - SQL 데이터베이스를 새 서버로 가져오는 중 오류가 발생했습니다. (0) | 2022.10.11 |
월 및 연도만 저장할 MySQL 데이터 유형 (0) | 2022.10.11 |
jQuery에서 제목을 URL 슬래그로 변환하는 방법 (0) | 2022.10.11 |