Symfony의 서비스에 저장소를 삽입하는 방법은 무엇입니까?
두 개의 개체를 ImageService
. 그중 하나는의 인스턴스이며 Repository/ImageRepository
다음과 같이 표시됩니다.
$image_repository = $container->get('doctrine.odm.mongodb')
->getRepository('MycompanyMainBundle:Image');
그렇다면 내 services.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);
}
}
다음은 나와 같은 Google 사용자를위한 정리 된 솔루션입니다.
업데이트 : 다음은 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
는 엔티티 관리자의 이름입니다.)
@=service('doctrine.orm.default_entity_manager').getRepository('MycompanyMainBundle:Image')
2017 년과 Symfony 3.3+ 는 이것을 훨씬 더 간단하게 만들었습니다. Symfony 4.x에서도 동일합니다.
더 일반적인 설명 은 내 게시물 How to use Repository with Doctrine as Service in Symfony 를 확인하십시오 .
코드에서해야 할 일은 SOLID 패턴 중 하나 인 상속보다 합성을 사용하는 것입니다 .
1. Doctrine에 직접 의존하지 않고 자신의 저장소 만들기
<?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;
}
}
토마스 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 엔터티 서비스를 정의합니다. 예를 들어 제 경우에는 다음을 정의합니다. (심포니 서비스를 정의하기 위해 PHP를 사용합니다.)
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine'),AppBundle\Entity\ContactEmail::class]);
상속으로
위에서 언급 한 동일한 1 단계
Extend the
RepositoryServiceAdapter
class for example: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); } }
Register service:
$container->register('ellakcy.db.contact_email',AppBundle\Services\Adapters\RepositoryServiceAdapter::class) ->serArguments([new Reference('doctrine')]);
Either the case you have a good testable way to function tests your database beavior also it aids you on mocking in case you want to unit test your service without the need to worry too much on how to do that. For example, let us suppose we have the following service:
//Namespace definitions etc etc
class MyDummyService
{
public function __construct(RepositoryServiceAdapter $adapter)
{
//Do stuff
}
}
And the RepositoryServiceAdapter adapts the following repository:
//Namespace definitions etc etc
class SomeRepository extends \Doctrine\ORM\EntityRepository
{
public function search($params)
{
//Search Logic
}
}
Testing
So you can easily mock/hardcode/emulate the behavior of the method search
defined in SomeRepository
by mocking aither the RepositoryServiceAdapter
in non-inheritance approach or the ContactEmailRepositoryServiceAdapter
in the inheritance one.
The Factory Approach
Alternatively you can define the following factory:
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);
}
}
And then Switch to php service annotation by doing the following:
Place this into a file ./app/config/services.php
(for symfony v3.4, .
is assumed your ptoject's root)
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/*');
And cange the ./app/config/config.yml
(.
is assumed your ptoject's root)
imports:
- { resource: parameters.yml }
- { resource: security.yml }
#Replace services.yml to services.php
- { resource: services.php }
#Other Configuration
Then you can clace the service as follows (used from my example where I used a Dummy entity named Item
):
$container->register(ItemRepository::class,ItemRepository::class)
->setFactory([new Reference(RepositoryFactory::class),'repositoryAsAService'])
->setArguments(['$entityManager'=>new Reference('doctrine.orm.entity_manager'),'$entityName'=>Item::class]);
Also as a generic tip, switching to php
service annotation allows you to do trouble-free more advanced service configuration thin one above. For code snippets use a special repository I made using the factory
method.
참고URL : https://stackoverflow.com/questions/12223176/how-to-inject-a-repository-into-a-service-in-symfony
'Nice programing' 카테고리의 다른 글
Java에서 중괄호를 생략해도 괜찮습니까? (0) | 2020.10.20 |
---|---|
sendAsynchronousRequest : queue : completionHandler를 사용하는 방법 : (0) | 2020.10.20 |
Visual Studio Team Services에서 팀 프로젝트 삭제 (0) | 2020.10.20 |
웹 사이트 구축 비용을 어떻게 청구합니까? (0) | 2020.10.20 |
Javascript는 Java에 비해 얼마나 빠릅니까? (0) | 2020.10.20 |