Вышла новая версия Symfony 7.2

Дата публикации: 2024-11-29
Просмотры: 66

Вышла очередная минорная версия Symfony 7.2
Как и все минорные обновления Symfony поддерживает обратную совместимость.
А это означает, что вы сможете легко обновиться, ничего не меняя в своем коде.

Вышла новая версия Symfony 7.2

Ниже перечислены некоторые изменения для этой версии:

Week, WordCount and Yaml Constraints

Symfony включает десятки ограничений для проверки данных в приложениях. В Symfony 7.2 добавляны три новых ограничения.

Week Constraint

Это ограничение проверяет, что заданная строка (или объект, реализующий Stringable интерфейс PHP) представляет собой допустимый номер недели в соответствии со стандартом ISO-8601

// src/Entity/Rental.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Rental
{
    #[Assert\Week]
    protected string $bookingWeek;
}

Это ограничение включает в себя параметры max и min для дальнейшего ограничения того, какие недели может выбрать пользователь:

// src/Entity/OnlineCourse.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class OnlineCourse
{
    #[Assert\Week(min: '2022-W01', max: '2022-W20')]
    protected string $startWeek;
}

Проверка того, является ли неделя действительной или нет, не так тривиальна, как кажется, поскольку в некоторых годах 53 недели вместо обычных 52. Благодаря этому новому ограничению вы теперь можете забыть об этих деталях и позволить Symfony обрабатывать логику проверки.

WordCount Constraint

Это ограничение проверяет, что строка (или объект, реализующий Stringable интерфейс PHP) содержит количество слов, попадающее в заданный диапазон от минимума до максимума:

// src/Entity/BlogPostDTO.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class BlogPostDTO
{
    #[Assert\WordCount(min: 100, max: 200)]
    protected string $content;
}

Подсчет слов — сложная для решения проблема. Вот почему это ограничение опирается на класс IntlBreakIterator из PHP. Это также сильно зависит от языка контента, поэтому вы можете использовать locale опцию для определения локали контента (по умолчанию она использует ту же, что и текущая локаль приложения).

Yaml Constraint

Несмотря на свои странности, YAML остается чрезвычайно популярным языком конфигурации. Вот почему было добавлено ограничение, которое проверяет, Stringable содержит ли данная строка (или объект) допустимый синтаксис YAML:

// src/Entity/Report.php
namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Report
{
    #[Assert\Yaml(message: "Your configuration doesn't have valid YAML syntax.")]
    private string $customConfiguration;
}

Вы также можете использовать любой из флагов конфигурации , определенных в компоненте Symfony Yaml:

#[Assert\Yaml(
    message: "Your configuration doesn't have valid YAML syntax.",
    flags: Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_DATETIME,
)]
private string $customConfiguration;

Expression Language Improvements

Компонент ExpressionLanguage предоставляет движок, который может компилировать и оценивать выражения. Основная цель компонента — позволить пользователям использовать выражения внутри конфигурации для более сложной логики. В Symfony 7.2 улучшили его новыми функциями.

Новые операторы языка выражений

Компонент ExpressionLanguage уже поддерживает некоторые бинарные операторы: &(and), |(or) и ^(xor). В Symfony 7.2 добавили поддержку остальных побитовых операторов: <<(сдвиг влево), >>(сдвиг вправо) и ~(not).

Эти операторы не самые популярные, но они полезны в таких сценариях, как работа с битовыми полями внутри выражений, например, флагами компонентов Yaml:

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;

$el = new ExpressionLanguage();

$el->evaluate('1 << 4');  // result: 16
$el->evaluate('32 >> 4'); // result: 2
$el->evaluate('~5');      // result: -6

Кроме того, добавлена xor поддержка логического оператора (этот оператор уже был доступен как бинарный оператор):

$el->evaluate('$a xor $b');  // true if either $a or $b is true, but not both

WhenNot Attribute

В Symfony 5.3 ввели атрибут #[When] как способ ограничить службы определенными средами конфигурации:

use Symfony\Component\DependencyInjection\Attribute\When;

// this class is only registered in the "dev" environment

#[When(env: 'dev')]
class SomeClass
{
    // ...
}

Это работает хорошо, но при работе с многочисленными реализациями сервисов (например, для тестов) может быть обременительно определять #[When] атрибут для каждого сервиса. Вот почему в Symfony 7.2 был введен противоположный атрибут: #[WhenNot].

Этот новый атрибут позволяет исключить службу из определенных сред:

use Symfony\Component\DependencyInjection\Attribute\WhenNot;

#[WhenNot(env: 'dev')]
class SomeClass
{
    // ...
}

// add the attribute multiple times to exclude it from several environments

#[WhenNot(env: 'dev')]
#[WhenNot(env: 'test')]
class AnotherClass
{
    // ...
}

Lazy Choice Loader

Поле EntityType, определенное Symfony Forms, позволяет вам представлять все значения, хранящиеся для некоторой Doctrine Entity, через <select> элемент HTML или коллекцию радиокнопок или флажков. Оно расширяет поле ChoiceType, один из самых универсальных (и сложных) типов в Symfony Forms.

Самый большой недостаток EntityType заключается в том, что он может вызвать проблемы с производительностью при рендеринге сущности со многими значениями. Распространенным решением является создание поля автозаполнения с использованием комбинации кода PHP и JavaScript.

В Symfony 7.2 это упрощено, LazyChoiceLoader который реализует стратегию загрузки выбора по требованию. Вы можете использовать его в типах форм с помощью choice_lazy опции:

$formBuilder->add('user', EntityType::class, [
    'class' => User::class,
    'choice_lazy' => true,
]);

Внутри этот загрузчик сохраняет список выбора пустым, пока не понадобятся значения (избегая ненужных запросов к базе данных). Когда значения формы предоставляются или отправляются, он извлекает и кэширует только необходимые варианты.

Часть frontend, необходимая для динамического отображения вариантов выбора пользователю, по-прежнему не предоставлена. Для этого можно использовать поле автозаполнения из Symfony UX.

String Component Improvements

Компонент String предоставляет объектно-ориентированный API для строк и работает с байтами, кодовыми точками UTF-8 и кластерами унифицированным образом. В Symfony 7.2 компонент был улучшен новыми функциями.

Added a kebab() Method

Компонент String уже определяет некоторые методы для изменения регистра заданных строк. Например, camel() для использования camelCase(Foo bar->fooBar) и snake() для использования snake_case(Foo Bar->foo_bar). В Symfony 7.2 добавили kebab() использование kebab-case:

use function Symfony\Component\String\u;

$string = u('symfonyIsGreat')->kebab();   // $string = 'symfony-is-great'
$string = u('Symfony is great')->kebab(); // $string = 'symfony-is-great'
$string = u('Symfony_is_Great')->kebab(); // $string = 'symfony-is-great'

New Truncation Modes

Компонент String определяет truncate() метод с двумя режимами работы:

// by default, contents are cut to strictly meet the desired length
u('Lorem Ipsum')->truncate(8);             // 'Lorem Ip'
// but you can also keep the last word entirely, even if that generates a longer string
u('Lorem Ipsum')->truncate(8, cut: false); // 'Lorem Ipsum'

В Symfony 7.2 добавлены новые режимы через TruncateMode::*:

// the default value is TruncateMode::Char which cuts the string at the exact given length
// (this is the same as the previous default behavior)
u('Lorem ipsum dolor')->truncate(8, cut: TruncateMode::Char);       // 'Lorem ip'

// returns up to the last complete word that fits in the given length without surpassing it
u('Lorem ipsum dolor')->truncate(8, cut: TruncateMode::WordBefore); // 'Lorem'

// returns up to the last complete word that fits in the given length, surpassing it if needed
// (this is the same as setting `cut: false` in the previous example)
u('Lorem ipsum dolor')->truncate(8, cut: TruncateMode::WordAfter);  // 'Lorem ipsum'

Simpler Single-File Symfony Applications

Symfony позволяет создавать однофайловые приложения, которые полезны для простых воркеров, микросервисов, инструментов CLI, минимальных API и т.д. Вот пример однофайлового приложения, как оно выглядело раньше:

// index.php
use App\Generator\NumberGenerator;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Attribute\Route;

require __DIR__.'/vendor/autoload.php';

class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    public function registerBundles(): array
    {
        return [
            new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
        ];
    }

    protected function configureContainer(ContainerConfigurator $container): void
    {
        $container->extension('framework', [
            'secret' => 'S0ME_SECRET'
        ]);

        // alternatively, define this in a configuration file and load it as:
        // $container->import(__DIR__.'/../config/framework.yaml');
    }

    #[Route('/random/{limit}', name: 'random_number')]
    public function randomNumber(int $limit, NumberGenerator $numberGenerator): JsonResponse
    {
        return new JsonResponse([
            'number' => $numberGenerator->generate($limit),
        ]);
    }
}

return static function (array $context) {
    return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
}

В Symfony 7.2 был упрощен MicroKernelTrait. Теперь то же самое приложение выглядит так:

// index.php
use App\Generator\NumberGenerator;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Attribute\Route;

require __DIR__.'/vendor/autoload.php';

class Kernel extends BaseKernel
{
    use MicroKernelTrait;

    #[Route('/random/{limit}', name: 'random_number')]
    public function __invoke(int $limit, NumberGenerator $numberGenerator): JsonResponse
    {
        return new JsonResponse([
            'number' => $numberGenerator->generate($limit),
        ]);
    }
}

return static function (array $context) {
    return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
}

Изменения, внесенные в Symfony 7.2:

  • Каталог config/ теперь необязателен, поэтому вы можете полностью его опустить, если определяете конфигурацию в configureContainer() методе;
  • Файл bundles.php также является необязательным, и registerBundles() метод теперь по умолчанию равен yield new FrameworkBundle();. Это устраняет необходимость определять этот метод, когда не загружены другие пакеты;
  • Поддержка внедрения сервисов в вызываемые действия с использованием __invoke() метода;
  • Параметр framework.secret теперь необязателен.

Об этих и других улучшениях вы можете почитать по ссылке ниже.
Ссылка на источник: https://symfony.com/blog/symfony-7-2-0-released

Предыдущая статья:

Вышла новая версия PHP 8.4
Поделиться статьей:

Комментарии (1):

Авторизуйтесь, для того, чтобы оставить комментарий. Войти на сайт
avatar
Григорий Стерин
2024-11-30 12:00
Новые версии выходят как по расписанию )
Подписка на новости
Узнавайте о новых статьях первыми.
Профиль