Давайте посмотрим, что произошло за прошедший месяц в мире PHP и Laravel.
Новости PHP
Первые альфа-версии PHP 8.4 доступны для тестирования
Вышли первые две альфа-версии, дающие начало выпуска PHP 8.4. Обновления будут выходить каждые две недели по определенному графику, а финальный выпуск ожидается 21 ноября.
Заморозка функций ожидается 13 августа, а это значит, что некоторые изменения еще могут попасть в выпуск. На данный момент наиболее заметными являются следующие изменения:
-
Функции для работы с массивами: array_find, array_find_key, array_any и array_all.
Напоминаю, что, с этого года сократился предрелизный цикл, вместо 6 релиз-кандидат версий, теперь будет 4, а каждая версия теперь поддерживается на год дольше.
Поздравляю Кельвина, Саки и Эрика!
Вышли PHP 8.2.21 и PHP 8.3.9
Выпуски с исправлениями ошибок вышли по расписанию.
Ядро PHP
Большинство новостей, связанных с ядром PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:
📊RFC: Static class
RFC, о котором мы говорили в прошлом выпуске, отклонен после голосования.
Еще один RFC из прошлого выпуска, после проведения голосования был принят
📣RFC: Allow int type argument to BCMath function
В настоящее время функции BCMath
принимают значения только в виде строк. Saki Takamachi предлагает разрешить передавать целочисленные значения.
На данный момент в PHP существует функция bcdiv
для деления чисел произвольной точности, а также функция bcmod для получения остатка после деления. Saki Takamachi предлагает добавить новую функцию bcdivmod
, чтобы получать частное и остаток за одну операцию в виде массива.
📣RFC: Property hook improvements
После внедрения хуков свойств, Ilija Tovilo и Larry Garfield нашли способ реорганизовать логику, чтобы увеличить производительность.
📣RFC: Asymmetric Visibility v2
Ilija Tovilo и Larry Garfield представили вторую версию своего RFC, который был отклонен в прошлом году. Ребята предлагают добавить синтаксис, подобный Swift, чтобы разрешить свойствам иметь отдельную («асимметричную») видимость для операций чтения и записи.
Laravel дайджест
Обновления Laravel
11.14.Adding Pest stubs to publish command
https://github.com/laravel/framework/pull/51933
PR затрагивает стабы. Уже давно PEST по-дефолту в Laravel, но при этом при публикации, стабов по PEST не было. Теперь будут.
11.14. Adds support for Markdown extensions to the Stringable class
https://github.com/laravel/framework/pull/51932
PR затрагивает Stringable-метод Markdown
. Мы уже знаем, что этот метод также стал поддерживать extensions
. Теперь передавать расширение в метод Markdown мы сможем через helper Stringable
:
$html = str('# My Heading')->markdown(extensions: [new HeadingPermalinksExtension()]);
11.14. Improvements for the ServeCommand (add more loves & elevate DX)
https://github.com/laravel/framework/pull/51957
PR затрагивает команду по запуску виртуального сервера и немного ее прокачивает. Output
до этого показывал время ответа в секундах и не все эндпоинты реквестов. После этого PR мы видим все эндпоинты каждого реквеста и также видим время ответа в миллисекундах:
11.14. Add support for acting on attributes through container
https://github.com/laravel/framework/pull/51934
Крутой PR, его еще не добавили в документацию, по крайней мере я не заметил. Итак, сервис контейнер теперь также будет поддерживать атрибуты. Появился метод whenHas
(на самом деле чуть позже в процессе ревью PR он переименован whenHas attributes, но сути не меняет). Давайте взглянем например:
#[Attribute(Attribute::TARGET_PARAMETER)]
class AuthGuard implements ContextualAttribute
{
public function __construct(
public readonly string $name
) {}
}
Далее, на уровне контейнера и нового метода мы делаем проверку. Если при Resolve
сервиса через контейнер у определенного свойства будет этот атрибут, то в функции мы решаем, что именно в данном случае мы с вами вернем.
final class MyService
{
public function __construct(
#[AuthGuard('api')]
private readonly Guard $guard
) {}
}
$service = Container::getInstance()->make(MyService::class);
Вот, например, у нас есть сервис, мы его получаем через контейнер, мы вешаем атрибут AuthGuard
и указываем, что name у нас API. И в таком случае при резолве этого сервиса у нас в свойстве guard будет не просто guard, а у нас сразу будет с указанным name API.
Но не спешите обновлять Laravel и играться с новым функционалом, давайте взглянем дальше, также добавлен метод afterResolvingAttribute
:
Container::getInstance()->afterResolvingAttribute(
attribute: OnTenant::class,
callback: function (OnTenant $attribute, Connector $connector) {
$connector->onTenant($attribute->tenant);
}
);
Мы получаем зависимость, которую резолвим через DI, если на ней висит указанный атрибут. И в данном примере мы видим коннектор с атрибутом OnTenant
и после резолва мы в этот коннектор дополнительно прокидываем определенную логику.
11.15. feat: add generics to Eloquent Builder and Relations
https://github.com/laravel/framework/pull/51851
PR у нас затрагивает Eloquent Builder и отношения, добавляя дженерики. Тем самым, в конечном итоге это упростит нам жизнь, и мы будем понимать, что именно у нас будет возвращаться в коллекциях определенных отношений и соответственно самих билдеров модели.
11.15. Add support for mime types in Resend mail transport
https://github.com/laravel/framework/pull/52006
PR у нас затрагивает класс mailable
:
public function attachments(): array
{
return [
Attachment::fromPath('/path/to/file')
->as('name.pdf')
->withMime('application/pdf'),
];
}
добавлен метод withMime
и для attachment мы сразу можем указать MimeType через Builder.
11.15. Feat: improve Factory generics, add generics to HasFactory
https://github.com/laravel/framework/pull/52005
Не уходим далеко от темы дженериков, также улучшения дошли до фабрик.
И мы также к трейту можем указать, какую именно фабрику будет возвращать модель:
// before
class User extends Authenticatable
{
use HasFactory;
protected function newFactory(): UserFactory
{
return UserFactory::new();
}
}
// after
class User extends Authenticatable
{
/** @use HasFactory */
use HasFactory;
protected static string $factory = UserFactory::class;
}
Очень полезно, так скоро дойдем и до того, что будем справляться и без плагина Laravel IDEA.
11.15. Ask About View Next To Name For Create Mail Command
https://github.com/laravel/framework/pull/52057
PR затрагивает команду по генерации класса и если требуется вьюхи, для отправки email-уведомлений. До этого нам нужно было указывать через аргументы, какая именно вью нужна.
Теперь нас ждет интерактивная форма, где мы укажем класс, укажем нужна ли нам вьюха либо не нужна, и все что нам требуется выберем прямо не отходя от консоли, без необходимости вспоминать какие там аргументы присутствуют:
11.15. Make Router Tappable
https://github.com/laravel/framework/pull/52051
Большой PR, который у нас затрагивает роутер. Добавился трейт Tappable
. Тем самым в роутере у нас будет доступен метод метод tap
. Если у вас большая инфраструктура: пакетная, с доменами, теперь не придется как ранее подключать кучу файлов, так же дополнительно в тестах подключать эти файлы и все будет выглядеть следующим образом:
class RouteRegistrar
{
private const string ENDPOINT = 'redacted';
public function __invoke(Router $router)
{
$router->post(self::ENDPOINT, WebhookController::class)->name(self::ENDPOINT);
}
}
$router
->tap(new Redacted1Webhooks\RouteRegistrar())
->tap(new Redacted2Webhooks\RouteRegistrar())
->tap(new Redacted3Webhooks\RouteRegistrar())
->tap(new Redacted4Webhooks\RouteRegistrar());
есть удобный класс, есть метод tap чтобы быстро их объявить и так же объявить в тестах, если это требуется.
11.16. Install Laravel Reverb version 1.0 instead of @beta
https://github.com/laravel/framework/pull/52096
Если используете Reverb при выполнении команды по установке Broadcasting, до этого устанавливалась бета-версия Reverb, а теперь же будет устанавливаться версия 1.0
11.16. Include 'success' console component
https://github.com/laravel/framework/pull/52112
PR затрагивает консольные команды, и также был добавлен компонент Success для вывода успешного уведомления. На скриншоте видим как это будет выглядеть:
11.17. Add whereLike clause to query builder
https://github.com/laravel/framework/pull/52147
PR затрагивает query builder. Для тех, кто через Macroable
прописывал дополнительно в builder методы whereLike
, whereNotLike
, orWhereLike
, orWhereNotLike
. Теперь все это будет в коробке.
whereLike($column, $value, $caseSensitive = false): Выполняет запрос LIKE с возможностью учета регистра.
whereNotLike($column, $value, $caseSensitive = false): Выполняет запрос NOT LIKE с возможностью учета регистра.
orWhereLike($column, $value, $caseSensitive = false): Добавляет предложение OR LIKE с дополнительной чувствительностью к регистру
orWhereNotLike($column, $value, $caseSensitive = false): Добавляет предложение OR NOT LIKE с дополнительной чувствительностью к регистру
После этого PR вы сможете добиться того же самого по тому же запросу.
$users = DB::table('users')
->whereLike('email', 'john.doe@example.com')
->get();
или для поиска с учетом регистра
$users = DB::table('users')
->whereLike('email', 'John.Doe@example.com', true)
->get();
PostgreSQL использует оператор ilike
для операций, нечувствительных к регистру, и оператор like
для операций, чувствительных к регистру.
MySQL использует оператор like
для операций, нечувствительных к регистру, и оператор like binary
для операций, чувствительных к регистру.
SQLite использует оператор like
для операций, нечувствительных к регистру. Для операций, чувствительных к регистру, SQLite поддерживает оператор glob
, который преобразует привязки, заменяя символы _ и %.
SQL Server по умолчанию использует оператор like
. Чувствительность к регистру в SQL Server определяется сортировкой базы данных или столбца. Если флаг чувствительности к регистру установлен в значение true
, система выдаст исключение.
Также поддержка Postgres с ilike
. Все это теперь в коробке. Пожалуйста, пользуйтесь.
В документации я пока что всего этого не заметил, но думаю к выпуску этого дайджеста либо на днях добавят.
11.17. Allow microsecond travel
https://github.com/laravel/framework/pull/52190
Tim Macdonald добавил поддержку микросекунд в travel
функционал. Пример:
travel(5)->microseconds()
Видео-версия дайджеста: