Модернизация конфигурации Symfony
Оглавление
- Переход с YAML на PHP
- Переход от массива строк к типизированным PHP объектам
- Используйте всю мощь статического анализа
Symfony добавляет сообщения об устаревании этих опций, но заметить их не так-то просто.
Сегодня мы покажем, как обнаружить их с помощью Rector, PHPStan и ещё одного фантастического инструмента.
Symfony Security известна тем, что почти в каждой версии Symfony происходят значительные изменения. То, что работало в прошлом…
# config/security.yml
security:
enable_authenticator_manager: true
…может быть изменено или удалено.
Это не работает в Symfony 7. Мы хотим получать предупреждение заранее, как только произошло изменение, и без запуска нашего кода. Другие PHP-проекты используют @deprecation
аннотации, отмечающие устаревшие методы, свойства, константы и классы прямо в коде в вашей любимой IDE.
Как насчёт YAML? В нём этого нет, поэтому сначала придётся перейти на PHP.
1. Переход с YAML на PHP
Нет необходимости возиться с ручным переходом. Используйте symplify/config-transformer, для автоматизации процесса:
composer require simplify/config-transformer --dev
vendor/bin/config-transformer switch-format config/security.yml
Он анализирует YAML, преобразует его в PHP формат и распечатывает:
# config/security.php
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$containerConfigurator->extension('security', [
'enable_authenticator_manager' => true,
]);
};
Задание выполнено!
Если это ваша первая конфигурация с поддержкой PHP, не забудьте обновить Kernel для загрузки PHP-файлов.
Теперь у нас есть PHP конфиги, но на самом деле — это просто ещё одна форма массива, заполненного строками.
Symfony может работать лучше, по крайней мере, начиная с Symfony 5.3.
2. Переход от массива строк к типизированным PHP объектам
Вместо массивов мы хотим получить нечто, что можно использовать в IDE — полностью типизированные объекты с автозаполнением методов.
Вы используете Symfony 5.3+? Если нет, то сначала обновитесь с помощью Rector. После этого вы сможете использовать Config Builder Classes.
Но есть одна загвоздка — сложно рассказать о них вашей IDE и PHPStan, потому что они не являются частью кода Symfony. Они генерируются на лету, основываясь на текущей версии Symfony.
Чтобы упростить процесс генерации, воспользуйтесь инструментом tomasvotruba/symfony-config-generator
, определяющим доступные классы расширений и генерирующим классы для построения конфигурации:
composer require tomasvotruba/symfony-config-generator --dev
vendor/bin/symfony-config-generator
Проверьте генерируемые классы в каталоге кэша Symfony:
/var/cache/Symfony
У нас есть классы для построения конфигураций и PHP с массивами строк.
Как перевести массивы в классы сборщика конфигурации
Rector поможет! Правила Symfony для Rector содержат одну маленькую жемчужину, помогающую на 99% автоматизировать работу — правило StringExtensionToConfigBuilderRector
. Добавьте его в ваш конфиг rector.php
:
# rector.php
use Rector\Config\RectorConfig;
use Rector\Symfony\CodeQuality\Rector\Closure\StringExtensionToConfigBuilderRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([
StringExtensionToConfigBuilderRector::class,
]);
};
Затем запустите Rector с файлом конфигурации:
vendor/bin/rector p config/security.php
И вуаля — вот ваша современная конфигурация Symfony security:
# config/security.php
use Symfony\Config\SecurityConfig;
return static function (SecurityConfig $securityConfig): void {
$securityConfig->enableAuthenticatorManager(true);
};
Примечание: для некоторых элементов, таких как firewall, roles и т.д., потребуется отдельный вызов переменной — PHPStan сориентирует вас.
Вы только что увеличили ценность своих конфигов на порядок:
- полное автозаполнение любой security конфигурации в IDE
- Больше не нужно копипастить строку
"firewall"
и читать документацию по опциям Symfony. - вы получите предупреждения от PHPStan, если допустили опечатку
Чтобы PHPStan работал и не жаловался на отсутствие классов, расположенных в /var/cache
, мы должны загрузить классы в конфигурацию PHPStan:
# phpstan.neon
parameters:
bootstrapFiles:
- var/cache/Symfony/Config/SecurityConfig.php
- var/cache/Symfony/Config/Security/ProviderConfig.php
- var/cache/Symfony/Config/Security/AccessControlConfig.php
- var/cache/Symfony/Config/Security/AccessDecisionManagerConfig.php
- var/cache/Symfony/Config/Security/FirewallConfig.php
- var/cache/Symfony/Config/Security/PasswordHasherConfig.php
- var/cache/Symfony/Config/Security/ProviderConfig.php
3. Используйте всю мощь статического анализа
Мы бы с удовольствием работали с проектом Symfony в такой форме, но подождите — это ещё не всё.
Что нам действительно нужно, так это получать ранние предупреждения об устаревании прямо в нашем CI до того, как мы решим обновляться. Конфиги недоступны в репозитории Symfony Github, так как они генерируются на лету.
Но когда мы посмотрим на файл в нашем проекте:
var/cache/Symfony/Config/SecurityConfig.php
Мы увидим, что метод enableAuthenticatorManager()
фактически устарел в Symfony 6.4:
/**
* @default true
* @param ParamConfigurator|bool $value
* @deprecated The "enable_authenticator_manager" option at "security" is deprecated.
* @return $this
*/
public function enableAuthenticatorManager($value): static
{
// ...
}
Теперь у нас есть:
- конфиги в PHP методах
- доступный PHPStan
- мы используем метод с маркером
@deprecated
Но этого недостаточно, чтобы позволить CI помочь нам. Одной детали не хватает… хотите угадать?
PHPStan предоставляет расширение, сообщающее о @deprecated
элементах прямо в CI:
composer require phpstan/phpstan-deprecation-rules --dev
Примечание: установите phpstan/extension-installer, если у вас его ещё нет:
composer require phpstan/extension-installer --dev
Давайте запустим PHPStan с нашим конфигом и посмотрим результат:
vendor/bin/phpstan a config/security.php
PHPStan завершится неудачей и сообщит нам об этом:
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
------ -------------------------------------------------------------------------
Line config.php
------ -------------------------------------------------------------------------
8 Call to deprecated method enableAuthenticatorManager()
of class Symfony\Config\SecurityConfig:
The "enable_authenticator_manager" option at "security" is deprecated.
------ -------------------------------------------------------------------------
Теперь вы защищены и можете приступать к исправлению устареваний, пока они не исчезли совсем.
В первый раз настройка может занять какое-то время, но вы быстро освоитесь. В долгосрочной перспективе стоимость возвращается тысячекратно, поскольку вы получите лучшую конфигурацию Symfony из всех существующих.
Счастливого кодинга!