Symfony 4 - как использовать служебные теги при автоматическом подключении всего пути

Я работаю над пакетом для 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']

Итак, мне было интересно, есть ли обходной путь, который я не мог найти, или я должен просто вручную добавить каждую службу?

Редактировать: Было бы неплохо иметь возможность использовать аннотацию в классе, чтобы при загрузке он «знал» свой тег, но я думаю, что он работает наоборот, загружая класс, потому что он был помечен определенным тег.

Не знаю, сработает ли это, но пробовали ли вы исключить каталоги репозитория (используя подстановочный знак) из своего первого ресурса? Это может предотвратить дублирование ключей. Я не понимаю, как вы предотвращаете определение своих сущностей как служб, что может иметь забавные последствия.

Cerad 31.03.2018 15:37

Ресурс ограничен файлами, оканчивающимися на *Manager.php и *Repository.php, поэтому объекты не являются службами.

VMC 10.04.2018 22:07

Немного не по теме, но мне любопытно, откуда берется этот тег doctrine.repository_service. Если ваш репозиторий расширяет ServiceEntityRepository, то для автоматического подключения тегов не требуется. Убедитесь, что вы расширяете, а не внедряете.

Cerad 10.04.2018 23:19

Это может быть актуально: github.com/symfony/maker-bundle/issues/98

Cerad 10.04.2018 23:24

Итак, глядя на DoctrineBundle ServiceRepositoryCompilerPass, вам нужен только тег, если вы не используете автозагрузку.

Cerad 10.04.2018 23:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
5
5
4 445
4

Ответы 4

Вы можете автоматически настраивать теги в своем классе ядра / основного пакета:

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! Пробовал как в комплекте, так и в ядре, как указано в документации. К сожалению, это не работает.

VMC 11.04.2018 09:12

Я столкнулся с тем же сообщением об ошибке после рефакторинга (переименования) некоторых сущностей и связанных репозиториев с помощью 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, как упоминалось в другом ответе, но это принесло мне счастье. В конце концов, автоматическая пометка не обязательна.

Arnie 06.12.2020 00:37

Другие вопросы по теме