Как переопределить любую часть пакета

При использовании сторонних пакетов вы можете захотеть настроить или переопределить некоторые из их функций. Этот документ описывает способы переопределения наиболее распространённых функций пакета.

Tip

Механизм переопределения пакета означает, что вы не можете использовать физические пути для ссылания на источники пакета (например, __DIR__/config/services.xml). Всегда используйте логические пути в ваших пакетах (например, @FooBundle/Resources/config/services.xml) и вызывайте метод locateResource(), чтобы преобразовывать их в физические пути при необходимости.

Шаблоны

Шаблоны сторонних бандлов могут быть переопределены в каталоге <your-project>/templates/bundles/<bundle-name>/. Новые шаблоны должны использовать то же имя и путь (относительно <bundle>/Resources/views/) как и оригинальные шаблоны.

Например, для переопределения шаблона Resources/views/Registration/confirmed.html.twig из FOSUserBundle, создайте этот шаблон: <your-project>/templates/bundles/FOSUserBundle/Registration/confirmed.html.twig

Caution

После добавления шаблона в новое место, возможно, вам необходимо будет очистить кеш (php bin/console cache:clear), даже если вы в debug-режиме.

Tip

Сам Symfony тоже использует некоторые бандлы, поэтому вы можете использовать этот же подход для переопределения шаблонов ядра Symfony. Например, вы можете настроить страницы ошибок переопределяя шаблоны TwigBundle.

Маршрутизация

Маршрутизация в Symfony никогда не импортируется автоматически. Если вы хотите включить маршруты из любого пакета, то они должны быть импортированы вручную откуда-то из вашего приложения (например, config/routes.yaml).

Самый простой способ "переопределить" маршрутизацию пакета - не импортировать её в принципе. Вместо импортирования маршрутизации стороннего пакета, просто скопируйте файл маршрутизации в ваше приложение, измените его и импортируйте.

Контроллеры

Если контроллер является сервисом, смотрите следующий раздел о том, как пеоепределить его. В обратном случае, определите новый маршрут + контроллер с одним путём, связанным с контроллером, который вы хотите переопределить (и убедитесь, что новый маршрут загружается до маршрута пакета).

Сервисы и конфигурация

Если вы хотите изменить определения сервисов другого пакета, вы можете испльзовать пропуск компилятора, чтобыизменить класс сервиса или чтобы изменить вызовы метода. В следующем примере, реализующий класс для original-service-id изменён на App\YourService:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// src/Kernel.php
namespace App;

// ...
+ use App\Service\YourService;
+ use Symfony\Component\DependencyInjection\ContainerBuilder;
+ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

class Kernel extends BaseKernel implements CompilerPassInterface
{
+     public function process(ContainerBuilder $container)
+     {
+         $definition = $container->findDefinition('original-service-id');
+         $definition->setClass(YourService::class);
+     }
}

Чтобы узнать больше о пропусках компилятора, см. How to Work with Compiler Passes.

Сущности и их отображение

В связи с особенностями работы Doctrine, невозможно переопределить отображение сущностей пакета. Однако, если пакет предоставляет отображённый суперкласс (как, например, сущность User в FOSUserBundle), то можно переопределить атрибуты и ассоциации. Узнайте больше об этой функции и её ограничениях в документации Doctrine.

Формы

Существующие типы форм могут быть изменены путём определения расширений типа формы.

Метаданные валидации

Symfony загружает все файлы конфигурации валидации из каждого пакета и комбинирует их в одно древо метаданных валидации. Это означает, что вы можете добавить новые ограничения к свойству, но не можете переопределить их.

Чтобы обойти это, сторонний пает должен иметь конфигурацию для групп валидации. Например, FOSUserBundle имеет такую конфигурацию. Чтобы создать вашу собственную валидацию, добавьте ограничения к новой группе валидации:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    # config/validator/validation.yaml
    FOS\UserBundle\Model\User:
        properties:
            plainPassword:
                - NotBlank:
                    groups: [AcmeValidation]
                - Length:
                    min: 6
                    minMessage: fos_user.password.short
                    groups: [AcmeValidation]
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    <!-- config/validator/validation.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
            http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
    
        <class name="FOS\UserBundle\Model\User">
            <property name="plainPassword">
                <constraint name="NotBlank">
                    <option name="groups">
                        <value>AcmeValidation</value>
                    </option>
                </constraint>
    
                <constraint name="Length">
                    <option name="min">6</option>
                    <option name="minMessage">fos_user.password.short</option>
                    <option name="groups">
                        <value>AcmeValidation</value>
                    </option>
                </constraint>
            </property>
        </class>
    </constraint-mapping>
    

Теперь, обновите конфигурацию FOSUserBundle так, чтобы он использовал ваши группы валидации вместо исходных.

Переводы

Переводы не связаны с пакетами, но связаны с доменами. Это означает, что вы можете переопределить переводы из любого файла перевода, если он находится на правильном домене.

Переводы относятся не к бандлам, а к доменам переводов. Поэтому вы можете переопределить файл перевода любого бандла из главного каталога translations/, нужно лишь убедиться, что новый файл использует тот же домен.

Например, для переопределения переводов, определённых в файле Resources/translations/FOSUserBundle.es.yml из FOSUserBundle, создайте файл <your-project>/translations/FOSUserBundle.es.yml.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.