Всем привет!
Это PHP Дайджест от CutCode. Давайте посмотрим, что произошло за прошедший месяц в мире PHP.
Новости PHP
Вышли PHP 8.2.19 и PHP 8.3.7
Выпуски с исправлениями ошибок вышли по расписанию.
Вышел Statamic 5
В новой версии CMS для Laravel улучшена производительность, по заверениям разработчиков, наблюдалось увеличение скорости от 50 до 600%. Также улучшена работа с командной строкой и добавлена возможность добавлять новые сайты непосредственно из админки.
Statamic 5 поддерживает Laravel 11, а также добавлена поддержка Laravel Reverb и Laravel Prompts.
Открыта программа раннего доступа PhpStorm 2024.2
В новой версии добавлена поддержка стиля кода PER, а также упрощен рефакторинг выражений.
Ознакомьтесь бесплатно с последними функциями, которые были добавлены в IDE до официального релиза.
Большинство новостей ядра PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:
✅ RFC: new MyClass()->method() without parentheses RFC Валентина Удальцова прошел этап голосования и был принят. Новый синтаксис, который позволит не оборачивать new выражения в cкобки при обращении к ним, появится в PHP 8.4.
Поздравляю Валентина с этим прекрасным начинанием и желаю новых одобренных RFC.
В телеграм-канале «Пых» уже набросали идей для новых RFC, напишите в комментариях, а что бы вы хотели добавить в PHP.
RFC был принят, четыре новые функции появятся в PHP 8.4:
● Функция array_find возвращает значение первого элемента, для которого $callback возвращает значение true. Если подходящий элемент не найден, функция возвращает NULL.
● Функция array_find_key возвращает ключ первого элемента, для которого $callback возвращает значение true. Если подходящий элемент не найден, функция возвращает NULL.
● Функция array_any возвращает значение true, если $callback возвращает значение true для любого элемента. В противном случае функция возвращает значение false.
● Функция array_all возвращает значение true, если $callback возвращает значение true для всех элементов. В противном случае функция возвращает значение false.
✅ RFC: Support object type in BCMath RFC, о котором мы говорили в прошлых выпусках, был также принят большинством голосов. Поддержка объектов типов в модуле BCMath появится в PHP 8.4.
? RFC: #[\Deprecated] Attribute
Benjamin Eberlei и Tim Düsterhus предлагают добавить новый атрибут #[\Deprecated] с необязательным текстовым сообщением и параметром since, для указания даты или версии, начиная с которых функция или константа объявлена устаревшими.
В настоящее время существует атрибут #[\JetBrains\PhpStorm\Deprecated] с необязательными параметрами reason, replacement и since, который поддерживается PhpStorm и статическими анализаторами.
?RFC: New ext-dom features in PHP 8.4
Niels Dossche продолжает улучшать модуль DOM. В этом RFC он предлагает добавить поддержку CSS-селекторов, добавить недостающие, но распространенные функции и добавить новые свойства.
?RFC: Transform exit() from a language construct into a standard function
Языковая конструкция exit может использоваться без скобок, если нет необходимости указывать параметр status.
Gina Peter Banyard предлагает изменить тип языковой конструкции exit на обычную функцию:
function exit(string|int $status = 0): never {}
Laravel дайджест
Обновления Laravel
11.7. Introduce method Rule::array()
https://github.com/laravel/framework/pull/51250
Первый PR затрагивает правила валидации. В класс Rule добавили новый метод Array. До этого у нас было правило валидации с Array в виде строки, часто приходилось пользоваться конкатенацией, и выглядело все это не очень красиво. Теперь с помощью объекта Rule и метода Array можно будет удобно взаимодействовать, передавать массивы, либо просто набор ключей через параметры, и даже поддерживаются коллекции. Таким образом, теперь возможно следующее:
Rule::array();
Rule::array('key_1', 'key_2', 'key_3');
Rule::array(['key_1', 'key_2', 'key_3']);
Rule::array(collect(['key_1', 'key_2', 'key_3']));
Rule::array([UnitEnum::key_1, UnitEnum::key_2, UnitEnum::key_3]);
Rule::array([BackedEnum::key_1, BackedEnum::key_2, BackedEnum::key_3]);
Я думаю, такой метод давно напрашивался.
11.7. Add ability to override the default loading cached Routes for application
https://github.com/laravel/framework/pull/51292
Следующий pull request затрагивает route. Я думаю, все вы прекрасно знаете, что route кэшируются в Laravel, но сама логика кэширования не поддавалась изменению до этого PR. Теперь это все вынесено в отдельный callback и вы можете переопределить логику кэширования, если это требуется.
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
...
RouteServiceProvider::loadCachedRoutesUsing(function(){
//logic here
});
}
11.7. Add ->whereJsonOverlaps() for mysql
https://github.com/laravel/framework/pull/51288
На этот раз queryBuilder и новый метод whereJsonOverlaps
, который под капотом будет использовать MySQL функцию JSON_OVERLAPS(). В PR расписали, что она из себя представляет, необходима для сравнения двух JSON документов и вернет true
, если хотя бы одна пара ключей у нас будет совпадать. Соответственно, первый параметр у нас поле в базе данных, второй - массив с набором ключей, которые мы сравниваем.
User::whereJsonOverlaps('languages', ['en', 'fr'])->exists();
User::whereJsonDoesntOverlap('languages', ['en', 'fr'])->exists();
Вот такой сахарный метод добавили в релизе 11.7
11.7. Add InteractsWithInput methods to ValidatedInput
https://github.com/laravel/framework/pull/51316
Следующий PR затрагивает объект reques
t метод safe
, который возвращает объект validatedInput
. И если работали просто с объектом request
, то в нем присутствовал trait InteractsWithInput
и были доступны методы field
, boolean
, exist
и так далее. Вот он список всех методов:
exists, hasAny, whenHas, filledisNotFilled, anyFilled, whenFilled, whenMissing, keys, input,str,string, boolean, integer, float, date, enum, dd, dump
Но при этом, когда мы обращались к объекту validatedInput
через safe
, у нас был скудный набор методов. Теперь и там присутствует вот этот trait, поэтому весь набор методов доступен:
$request->safe()->filled('test');
$request->safe()->boolean('test');
11.7. Adding PasswordResetLinkSent event
https://github.com/laravel/framework/pull/51253
И напоследок по релизу 11.7 - добавился новый event, который срабатывает, когда мы отправляем ссылку по сбросу пароля. Теперь у нас присутствует это событие и мы можем с вами с ним взаимодействовать.
11.8. Create new "has" validation rule
https://github.com/laravel/framework/pull/51348
PR по правилам валидации. Добавили новое правило валидации has, как указано в title, но на самом деле позже оно было переименовано и стало contains. Его уже и добавили в документацию. Правило сделали для того, чтобы проверить, есть ли значения в массиве из request.
Например, предположим, что вы настраиваете возможность ограничения доступа к определенным IP-адресам. Вы можете настроить некоторые правила следующим образом:
return [
'allowed_ips' => ['present', 'nullable', 'array'],
'allowed_ips.*' => ['required', 'ip'],
];
Однако, необходимо убедиться, что IP-адрес текущего пользователя включен в предоставленный массив входных данных. Действующие правила не предусматривают возможности сделать это. С новым правилом contains будет выглядеть следующим образом:
return [
'allowed_ips' => ['present', 'nullable', 'array', contains:' . $request->ip()],
'allowed_ips.*' => ['required', 'ip'],
];
11.8. Allow adding array or string for web and api routes in bootstrap/app.php
https,//github.com/laravel/framework/pull/51356
Следующий важный PR касается bootstrap/app.php
. До этого мы внутри могли указать web route и api route в виде строки, теперь же можем указывать в виде массива и сразу подключать несколько файлов с route. Я думаю, так гораздо удобнее, чем как ранее, когда могли подключить только один файл и внутри уже делать require.
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: [
__DIR__.'/../routes/web.php',
__DIR__.'/../admin/web.php',
],
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
//
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();```
11.8. Adds ability to manually fail a command from outside the handle() method
https,//github.com/laravel/framework/pull/51435
Следующий PR по Jobs. Теперь можно через метод fail
самостоятельно зафейлить выполняющуюся job:
public function handle()
{
$this->trigger_failure();
}
protected function trigger_failure()
{
$this->fail('Whoops!');
}
11.8. MailMakeCommand, Add new --view option
https://github.com/laravel/framework/pull/51411
Небольшой pull request на make:mail
команду, которая создает класс по отправке email уведомлений и помимо самого класса создаст и view для email.
11.8. Add the events to be displayed on the model:show command
https://github.com/laravel/framework/pull/51324
Прокачали команду model:show
. Теперь она нам также показывает и все объявленные события в модели.
11.9. Изменения в composer.json
Зависимостей стало еще меньше и мы не видим с вами привычный spatie/ignition, который отвечал за страницу с ошибкой. Также у страницы с ошибкой новый вид:
Теперь она у нас прямо из коробки, выглядит компактно. Здесь минимум информации, но выглядит все стильно. Я думаю сразу у вас возникает вопрос, а как быть, та страница spatie/ignition
была намного круче? Не переживайте, можно сделать следующее:
composer require spatie/laravel-ignition
просто установить зависимость, и после установки мы видим с вами знакомую нам страницу с ошибкой.
11.9. Prevent destructive commands from running
https://github.com/laravel/framework/pull/51376
Появилась интересная фича - новый trait для консольных команд. Внутри - статический метод который позволяет не вызывать в продакшене деструктивные команды. Метод называется Prohibit
и в итоге мы с вами прямо в сервис-провайдере можем указать, что MigrateFresh
, MigrateRefresh
и остальные деструктивные команды не будут вызываться в продакшене, даже если укажете force.
public function boot(): void
{
FreshCommand::prohibit($this->app->isProduction());
RefreshCommand:: prohibit($this->app->isProduction());
ResetCommand:: prohibit($this->app->isProduction());
WipeCommand:: prohibit($this->app->isProduction());
}
Также в рамках фасада DB появился статический метод, чтобы сразу вызвать этот новый метод для всех деструктивных команд.
DB::prohibitDestructiveCommands($this->app->isProduction());
Видео-версия дайджеста: