Symfony 6.4 – невозможно объявить абстрактный тип формы как услугу

В моем проекте Symfony 6.4 я пытаюсь объявить абстрактный сервис в Services.yaml, выполнив следующие действия:

конфигурация/services.yaml

imports:
- { resource: services/ }
services:
# default configuration for services in *this* file
    _defaults:
       autowire: true      # Automatically injects dependencies in your services.
       autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

config/services/forms.yaml

services:
  _defaults:
    autowire: true
    autoconfigure: true

  # parent form
  App\Admin\Form\HostingFormAbstract:
    arguments:
      $authorizationChecker: '@security.authorization_checker'
      $tokenStorage: '@security.token_storage'
      $phpHandlers: '%php_handlers%'
      $nodeJsHandlers: '%nodeJs_handlers%'
    abstract:  true

  # children forms
  App\Admin\Form\HostingFormCreate:
    parent: App\Admin\Form\HostingFormAbstract
    class: App\Admin\Form\HostingFormCreate
    calls:
      - [setGroupManager, ['@App\Services\Managers\GroupManager']]
    tags: [form.type]

  App\Admin\Form\HostingFormUpdate:
    parent: App\Admin\Form\HostingFormAbstract
    class: App\Admin\Form\HostingFormUpdate
    calls:
      - [setHostnameManager, ['@App\Services\Managers\HostnameManager']]
    tags: [form.type]
...

Класс HostingFormAbstract расширяет AbstractType из пакета symfony/form:

namespace App\Admin\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints\NotBlank;

abstract class HostingFormAbstract extends AbstractType
{
    
    private TokenStorageInterface $tokenStorage;
    private AuthorizationCheckerInterface $authorizationChecker;
    private array $phpHandlers;
    private array $nodeJsHandlers;

    public function __construct(TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authorizationChecker, array $phpHandlers, array $nodeJsHandlers)
    {
        $this->tokenStorage = $tokenStorage;
        $this->authorizationChecker = $authorizationChecker;
        $this->phpHandlers = $phpHandlers;
        $this->nodeJsHandlers = $nodeJsHandlers;
    }
...

И при этом я получаю следующую ошибку при работе с моим приложением Symfony:

The service "App\Admin\Form\HostingFormAbstract" tagged "form.type" must not be abstract.

Для большего контекста я переписываю приложение Symfony 3.4 в новое приложение Symfony 6.4.

В версии 3.4 все работало нормально, но теперь кажется, что в Services.yaml нельзя объявить абстрактный сервис/класс, расширяющий класс AbstractType.

Я попытался добавить собственный тег в yaml для этого сервиса, но это ничего не изменило.

Я не нашел обходного пути в документации Symfony, и мне кажется странным, что вы не можете этого сделать. Возможно, я что-то пропустил.

Если у кого-нибудь есть идеи, как это сделать...

Спасибо !

Изменить, рабочее решение:

Кажется, что-то не так с моими несколькими файлами .yaml, регистрирующими службы.

Вот что мне нужно было сделать, чтобы зарегистрировать мой сервис:

  • Я переместил все службы из config/services/forms.yaml в config/services.yaml.
  • Я добавил autoconfigure: false в свой сервис App\Admin\Form\HostingFormAbstract.

конфигурация/services.yaml

imports:
- { resource: services/ }

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

    # makes classes in src/ available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    App\:
        resource: '../src/'
        exclude:
            - '../src/DependencyInjection/'
            - '../src/Entity/'
            - '../src/Kernel.php'
 ...

App\Admin\Form\HostingFormAbstract:
    class: App\Admin\Form\HostingFormAbstract
    autoconfigure: false
    arguments:
        $authorizationChecker: '@security.authorization_checker'
        $tokenStorage: '@security.token_storage'
        $phpHandlers: '%php_handlers%'
        $nodeJsHandlers: '%nodeJs_handlers%'
    abstract: true

App\Admin\Form\HostingFormCreate:
    parent: App\Admin\Form\HostingFormAbstract
    class: App\Admin\Form\HostingFormCreate
    calls:
        - [ setGroupManager, [ '@App\Services\Managers\GroupManager' ] ]
    tags: [ form.type ]

App\Admin\Form\HostingFormUpdate:
    parent: App\Admin\Form\HostingFormAbstract
    class: App\Admin\Form\HostingFormUpdate
    calls:
        - [ setHostnameManager, [ '@App\Services\Managers\HostnameManager' ] ]
    tags: [ form.type ]

Вы пытаетесь внедрить HostingFormAbstract напрямую в какое-то место? Обычно у вас есть несколько дополнительных классов форм, расширяющих HostingFormAbstract, которые имеют атрибут контейнера службы parent. symfony.com/doc/current/service_container/parent_services.ht‌​ml

Cerad 11.06.2024 14:18

Да, я добавляю HostingFormAbstract в некоторые дочерние службы. Я обновил код блока services.yaml в своем посте, чтобы показать вам, как я это делаю. @Серад

CTR 11.06.2024 16:55

Похоже, это должно сработать. Может быть, autowire подбирает класс без файла определения вашего сервиса? У вас есть только один файл Services.yaml?

Cerad 11.06.2024 17:33

У меня есть несколько файлов yaml, в которых я устанавливаю сервисы. Существует основной файл services.yaml, и я создал несколько других файлов .yaml, в которых заполняю некоторые сервисы, соответствующие категории (forms.yaml, admins.yaml, commands.yaml и т. д.). Эти файлы находятся в подпапке под названием «services», и я импортирую их через основной файл services.yaml с помощью ключа «imports». Я обновил свой пост, чтобы было более понятно.

CTR 12.06.2024 11:45

Возможно, я нахожусь на совершенно неправильном пути, но autowire может дважды подключить ваш абстрактный класс из-за нескольких файлов Services.yaml. В частности, если ваш главный файл config/service.yaml содержит обычные строки `App\:resource: '../src/'`, то он подберет все и попытается создать одну и ту же службу дважды.

Cerad 12.06.2024 14:44

Я также думал, что это может быть проблема, связанная с моими разными файлами .yaml, но у меня не было проблем с другими службами, столь же постоянными, как эта, ни в одном из других файлов .yaml... Если я зарегистрирую службу HostingFormAbstract в главное services.yaml К сожалению, у меня такая же проблема :/

CTR 13.06.2024 10:06

На самом деле ты был совершенно прав @Cerad, это была часть проблемы, спасибо! Другая часть была в ответе yceruto

CTR 13.06.2024 10:39
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать 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 и хотите разрабатывать...
2
7
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это поведение по умолчанию для параметра autoconfigure: тег form.type устанавливается для всех классов FormTypeInterface в области действия службы.

Однако вы можете исключить любую услугу из автоматической пометки, установив autoconfigure: false следующим образом:

App\Admin\Form\HostingFormAbstract:
    autoconfigure: false
    // ...

и тогда ошибка должна исчезнуть.

Вы правы, он работает, если для автоконфигурации установлено значение false! Но это не единственное, что мне пришлось сделать: я также переместил свою службу HostingFormAbstract и все дочерние службы в мой основной файл Services.yaml вместо form.yaml, чтобы регистрация работала. Итак, @Cerad тоже был прав: что-то не так с моими файлами нескольких служб. Спасибо вам обоим за помощь!

CTR 13.06.2024 10:16

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