Symfony 2: Репозиторийден қызметті құру

Symfony үйреніп жатырмын және репозиторийді пайдалану арқылы қызметті құруға тырысамын. Мен репозиторийлерімді және субъектілерімді генерациялаудан құрдым: субъект, сондықтан олар жақсы болуы керек.

Әлі күнге дейін менің қызметтерімде алған нәрсе:

parameters:
    mytest.entity: TestTestBundle:Brand
    mytest.class:  Test\TestBundle\Entity\Brand
    default_repository.class: Doctrine\ORM\EntityRepository

services:
     myservice:
          class: %default_repository.class%
          factory-service: doctrine.orm.default_entity_manager
          factory-method: getRepository
          arguments:
            - %mytest.entity%

Бірақ мен қызметке қоңырау шалсам, қатені аламын:

Catchable Fatal Error: Argument 2 passed to Doctrine\ORM\EntityRepository::__construct() must be an instance of Doctrine\ORM\Mapping\ClassMetadata, none given, called in 

Содан кейін мен ұйымды пайдалана отырып, қызметті жасауға тырыстым. My services.yml келесідей көрінеді:

services:
     myservice:
          class: %mytest.class%
          factory-service: doctrine.orm.default_entity_manager
          factory-method: getRepository
          arguments:
            - %mytest.entity%

Бірақ бұл үшін мен:

Error: Call to undefined method 
                Test\TestBundle\Entity\Brand::findAll

Не істеп жатқанымды ешкім білмейді ме?

Рахмет

17

7 жауаптар

DEPRECATION WARNING: No more factory_service and factory_method. This is how you should do it since Symfony 2.6 (for Symfony 3.3+ check below):

parameters:
    entity.my_entity: "AppBundle:MyEntity"

services:
    my_entity_repository:
        class: AppBundle\Repository\MyEntityRepository
        factory: ["@doctrine", getRepository]
        arguments:
            - %entity.my_entity%

Жаңа setFactory() әдісі болды Symfony 2.6-де енгізілген. 2.6 дейін зауыттар үшін синтаксисті ескі нұсқаларын қараңыз.

http://symfony.com/doc/2.7/service_container/factories.html

EDIT: Looks like they keep changing this, so since Symfony 3.3 there's a new syntax:

# app/config/services.yml
services:
    # ...

    AppBundle\Email\NewsletterManager:
        # call the static method
        factory: ['AppBundle\Email\NewsletterManagerStaticFactory', createNewsletterManager]

Check it out: http://symfony.com/doc/3.3/service_container/factories.html

41
қосылды
Awesome thx көп :)
қосылды автор shokora, көзі
@userfuser конструкторды жоюға тырыстыңыз ба? Онда барлық жаңа тәуелділіктерді қосуға болады, тек Doctrine күтетінін қамтамасыз ету үшін parent :: __ construct ($ arg) деп қоңырау шалыңыз.
қосылды автор Francesco Casula, көзі
Бұл жақсы жұмыс істейді, tnx. Бірақ мен тағы бір қадам алайын деп едім: егер мен осы репозиторийге қызметті енгізгім келсе де (мысалы, Paginator қызметі деп айтайын)? Мен оған қосымша артықшылықтарды енгізуге тырыстым, бірақ бұл жұмыс істемейді, себебі Symfony - бұл мен бергендердің ешқайсысын «күтпейді».
қосылды автор userfuser, көзі
@FrancescoCasula Мен ойладым, бірақ мен оны репо барлық жаһандық өзгертуге әзірге дайын емес, өйткені бұл инъекция бірнеше жағдайларда ғана қажет болды. Ақыр соңында, мен осы нақты жағдайға құжаттарды анықтағандай, баптау инъекциясын қолданып жасадым: symfony.com/doc/current/service_container/…
қосылды автор userfuser, көзі
Тек жұмыс істейді, рахмет!
қосылды автор Marcelo Rodrigo, көзі

Here is how we did it in KnpRadBundle: https://github.com/KnpLabs/KnpRadBundle/blob/develop/DependencyInjection/Definition/DoctrineRepositoryFactory.php#L9

Соңында:

my_service:
    class: Doctrine\Common\Persistence\ObjectRepository
    factory_service: doctrine # this is an instance of Registry
    factory_method: getRepository
    arguments: [ %mytest.entity% ]

ЖАҢАРТУ

2.4-тен кейін, доктринасы әдепкі репозитарий зауытын ауыстыруға мүмкіндік береді.

Here is a possible way to implement it in symfony: https://gist.github.com/docteurklein/9778800

24
қосылды
бұл github.com/doctrine/common/blob/master/lib/Doctrine/Common/& hellip; . Сіз EntityManager данасымен бірдей әрекет ете аласыз. Шындығында class: мұнда маңызды емес, себебі ол фабрика қызметі болғандықтан, контейнер берілген сыныптың өзін растайды, бірақ оны орындау үшін қызметтердің әдісін сұрайды.
қосылды автор Florian, көзі
бірақ класы: Doctrine \ Common \ Persistence \ ObjectRepository дұрыс емес, себебі қайтарылған данасы шынымен ObjectRepository интерфейсін
қосылды автор Florian, көзі
Айтпақшы, менің мысал жұмыс істейді ме?
қосылды автор Florian, көзі
Қызмет көрсету қоқысының нәтижесін ( app/cache/dev/appDevDebugProjectContainer.php бөлімінде орналасқан) салыңыз ба? Әдісті атау керек: getMyserviceService (сіздің мысалға негізделген).
қосылды автор Florian, көзі
және сізге қызмет анықтамасы бар ма?
қосылды автор Florian, көзі
HAHA! Мен оны алдым :) factory_service және factory-service болуы керек деп ойлаймын. _ жазыңыз.
қосылды автор Florian, көзі
Мен ұялып, жеткілікті рахмет айта алмаймын! Мен бас тартқым келді. Өте рахмет!
қосылды автор Strnm, көзі
Рахмет Флориан: қорғалған функция getMyserviceService() {return $ this-> services ['myservice'] = new \ Test \ TestBundle \ Entity \ Repository \ BrandRepository ('TestTest & zwnj; Bundle: Brand'); }
қосылды автор Strnm, көзі
Флорианға рахмет. Жоқ, олай емес, не дұрыс емес нәрсе жасаймын, бірақ айтқанымдай: FatalErrorException: Қате: Интерфейсті Doctrine \ Common \ Persistence \ ObjectRepository in
қосылды автор Strnm, көзі
Рақмет, Егер Доктрина \ Жалпы \ Тұрақтылық \ ObjectRepository болса, оны қалай жасауға болады? factory-service: доктрина # бұл - тізілімнің мысалы, бұл doctrine.orm.default_entity_manager?
қосылды автор Strnm, көзі

Сіз қате YAML-кілттерін қолданған боларсыз. Сіздің бірінші конфигурацияңыз мен үшін жақсы жұмыс істейді

  • зауыттық қызметтің орнына factory_service
  • зауыттық әдіс орнына factory_method
10
қосылды
Бұл мен үшін өте пайдалы, рахмет. Мен сондай-ақ кейбір желтоқсан айында жарияланған кейбір ескертулер - Мен мұнда сілтеме қалдырамын, егер біреу де осындай нәрсе іздесе.
қосылды автор Ivan Kolmychek, көзі

Since 2017 and Symfony 3.3+ this is now much easier.

Ескерту: generate: entity сияқты жалпы пәрмендерден аулақ болуға тырысыңыз. Олар жоба жұмысын жылдам бастауға тілек білдірушілерге арналған. Олар жаман тәжірибелерді жояды және өзгерту үшін өте ұзақ уақыт алады.

Check my post How to use Repository with Doctrine as Service in Symfony for more general description.

Сіздің код:

1. Update your config registration to use PSR-4 based autoregistration

# app/config/services.yml
services:
    _defaults:
        autowire: true

    Test\TestBundle\:
        resource: ../../src/Test/TestBundle

2. Мұрагерлік құрамы - Doctrine-ге тікелей тәуелді болмай жеке репозиторийді жасаңыз

<?php

namespace Test\TestBundle\Repository;

use Doctrine\ORM\EntityManagerInterface;

class BrandRepository
{
    private $repository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->repository = $entityManager->getRepository(Brand::class);
    }

    public function findAll()
    {
        return $this->repository->findAll();
    }
}

3. Конструкторлық инжекция арқылы кез-келген Қызмет немесе Контроллерде пайдаланыңыз

use Test\TestBundle\Repository\BrandRepository;

class MyController
{
    /**
     * @var BrandRepository
     */
    private $brandRepository;

    public function __construct(BrandRepository $brandRepository)
    {
        $this->brandRepository = $brandRepository;
    }

    public function someAction()
    {
        $allBrands = $this->brandRepository->findAll();
       //...
    }

}
2
қосылды
Басқа нәрсе - мен де Doctrine \ ORM \ EntityManagerInterface: {alias: doctrine.orm.default_entity_manager}
қосылды автор iisisrael, көзі
Бұл автоталандыру арқылы қызметті жасайды, бірақ бұл қызмет мәселені шешпейтін репозиторийдің өзі емес. Test \ TestBundle \ Entity \ Brand қызметіне атын өзгерту арқылы түпнұсқа конфигурация автоматты түрде жұмыс істейтін болады class , factory_service және factory_method конфигурациялары және зауытты қосу: 'Doctrine \ ORM \ EntityManagerInterface: getRepository' . Және, мүмкін, дәлелді орап алу. Мен әлі күнге дейін ұқсас конфигурациясы бар ағымдағы жобаға рефакторинг жасай аламын, сондықтан мен мүлдем айта алмаймын, бірақ кем дегенде кэшті тазарту үшін алдым.
қосылды автор iisisrael, көзі

sf 2.6+

parameters:
    mytest.entity: TestTestBundle:Brand
    mytest.class:  Test\TestBundle\Entity\Brand
    default_repository.class: Doctrine\ORM\EntityRepository

services:
     myservice:
          class: %default_repository.class%
          factory: ["@doctrine.orm.default_entity_manager", "getRepository"]
          arguments:
            - %mytest.entity%
2
қосылды
SO-қа қош келдіңіз. Егер сіз бұл мәселені шешетін болсаңыз, кейбір түсіндірмелерді қоссаңыз болады.
қосылды автор René Vogt, көзі
symfony.com/doc/2.6/components/dependency_injection/… Symfony \ Component \ DependencyInjection \ Definition :: setFactory & zwnj; 2.6 нұсқасынан кейін әдіс (getRepository & zwnj;) 3.0-де жойылады. Сипаттаманы пайдалану :: setFactory ()
қосылды автор user3665895, көзі

Symfony 3.3 and doctrine-bundle 1.8 there is a Doctrine\Bundle\DoctrineBundle\Repository\ContainerRepositoryFactory which helps to create repository as service.

Мысал

Біз қалайтын нәрсе

$rep = $kernel->getContainer()
    ->get('doctrine.orm.entity_manager')
    ->getRepository(Brand::class);

ORM сипаттамасы

# Brand.orm.yaml
...
repositoryClass: App\Repository\BrandRepository
...

Қызмет сипаттамасы

# service.yaml

App\Repository\BrandRepository:
    arguments:
      - '@doctrine.orm.entity_manager'
      - '@=service("doctrine.orm.entity_manager").getClassMetadata("App\\Entity\\Brand")'
    tags:
        - { name: doctrine.repository_service }
    calls:
        - method: setDefaultLocale
          arguments:
              - '%kernel.default_locale%'
        - method: setRequestStack
          arguments:
              - '@request_stack'
0
қосылды

Service.yml қызметіне service.xml түрлендіріп, DependencyInjection Extension жаңартуды, барлығы мен үшін жұмыс істейді. Мен неге екенін білмеймін, бірақ yml config Catchable Fatal Error-ты тастайды. Қызмет теңшелімі үшін xml теңшелімін пайдаланып көріңіз.

service.yml:

services:
    acme.demo.apikey_userprovider:
        class: Acme\DemoBundle\Entity\UserinfoRepository
        factory-service: doctrine.orm.entity_manager
        factory-method: getRepository
        arguments: [ AcmeDemoBundle:Userinfo ]

    acme.demo.apikey_authenticator:
        class: Acme\DemoBundle\Security\ApiKeyAuthenticator
        arguments: [ "@acme.demo.apikey_userprovider" ]

service.xml:


    
        AcmeDemoBundle:Userinfo
    

    
        
    

0
қосылды
yml кілттеріңіз дұрыс емес, бұл factory-service болуы тиіс factory_service (астын сызу).
қосылды автор Eddie Jaoude, көзі