Я работаю над пакетом для Symfony 4, который имеет такую структуру:
\Acme
\FooBundle
\Article
\Entity
- Article.php
- Comment.php
\Form
- ArticleType.php
\Repository
- ArticleRepository.php
- CommentRepository.php
- ArticleManager.php
\User
\Entity
- User.php
\Repository
- UserRepository.php
- UserManager.php
\SomethingElse
\Entity
- SomethingElse.php
\Repository
- SomethingElseRepository.php
- SomethingElseManager.php
Есть еще много папок и сущностей, но это не имеет отношения к вопросу.
Автоматическое подключение всех классов в этой папке можно создать с помощью такой конфигурации:
Acme\FooBundle\:
resource: '../../*/{*Manager.php,Repository/*Repository.php}'
exclude: '../../{Manager/BaseManager.php,Repository/BaseRepository.php}'
autowire: true
Но когда вам нужно добавить служебные теги, такие как doctrine.repository_service, такая конфигурация больше не поможет. Без тега при использовании в контроллере, например:
$this->getDoctrine()->getRepository(Bar::class)
или же
$this->getDoctrine()->getManager()->getRepository(Bar::class)
выдает ошибку:
The "Acme\FooBundle\SomethingElse\Repository\SomethingElseRepository" entity repository implements "Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepositoryInterface", but its service could not be found. Make sure the service exists and is tagged with "doctrine.repository_service".
Дело в том, что, поскольку все они находятся в одной корневой папке, мне не разрешено использовать конфигурацию, подобную следующей, потому что в ней были бы дублированы ключи Acme\FooBundle\:
Acme\FooBundle\:
resource: '../../*/{*Manager.php}'
exclude: '../../{Manager/BaseManager.php}'
autowire: true
Acme\FooBundle\:
resource: '../../*/{Repository/*Repository.php}'
exclude: '../../{Repository/BaseRepository.php}'
autowire: true
tags: ['doctrine.repository_service']
Итак, мне было интересно, есть ли обходной путь, который я не мог найти, или я должен просто вручную добавить каждую службу?
Редактировать: Было бы неплохо иметь возможность использовать аннотацию в классе, чтобы при загрузке он «знал» свой тег, но я думаю, что он работает наоборот, загружая класс, потому что он был помечен определенным тег.
Ресурс ограничен файлами, оканчивающимися на *Manager.php и *Repository.php, поэтому объекты не являются службами.
Немного не по теме, но мне любопытно, откуда берется этот тег doctrine.repository_service. Если ваш репозиторий расширяет ServiceEntityRepository, то для автоматического подключения тегов не требуется. Убедитесь, что вы расширяете, а не внедряете.
Это может быть актуально: github.com/symfony/maker-bundle/issues/98
Итак, глядя на DoctrineBundle ServiceRepositoryCompilerPass, вам нужен только тег, если вы не используете автозагрузку.






Вы можете автоматически настраивать теги в своем классе ядра / основного пакета:
https://symfony.com/doc/current/service_container/tags.html#autoconfiguring-tags
<?php
namespace Acme\FooBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class FooBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->registerForAutoconfiguration(EntityRepository::class)
->addTag('doctrine.repository_service');
}
}
Спасибо за ответ, @MakG! Пробовал как в комплекте, так и в ядре, как указано в документации. К сожалению, это не работает.
Я столкнулся с тем же сообщением об ошибке после рефакторинга (переименования) некоторых сущностей и связанных репозиториев с помощью PhpStorm 2019.2 Рефакторинг не обновил имя класса репозитория в блоке документации для сущности:
* @ORM\Entity(repositoryClass = "App\Repository\OldRepository")
Поэтому я щелкнул правой кнопкой мыши> Copy Reference, чтобы получить полное имя NewRepository, и вставил его в ссылку на блок документа:
* @ORM\Entity(repositoryClass = "\App\Repository\NewRepository")
PhpStorm снабдил класс префиксом обратной косой черты, и я не заметил этого, пока не попробовал множество комбинаций предлагаемых решений для этой ошибки. Мне нужно было только удалить обратную косую черту, и ошибка исчезла:
* @ORM\Entity(repositoryClass = "App\Repository\NewRepository")
Вы можете пометить все свои репозитории, например:
App\Repository\:
resource: '../src/Repository'
autowire: true
tags: ['doctrine.repository_service']
У меня было такое же сообщение об ошибке после обновления до Symfony 4.4 с 3.4.
Проблема заключалась в том, что у объекта была аннотация к @ORM\Entity(repositoryClass = "App\Repository\MyRepository").
в то время как репозиторий расширяет ServiceEntityRepository и в конструкторе указывает на сущность parent::__construct($registry, MyEntity::class);.
Удаление аннотации к объекту устранило проблему.
Спасибо вам миллион, сэр! Я пробовал использовать автоматические теги через services.yml, как упоминалось в другом ответе, но это принесло мне счастье. В конце концов, автоматическая пометка не обязательна.
Не знаю, сработает ли это, но пробовали ли вы исключить каталоги репозитория (используя подстановочный знак) из своего первого ресурса? Это может предотвратить дублирование ключей. Я не понимаю, как вы предотвращаете определение своих сущностей как служб, что может иметь забавные последствия.