Всем привет!
Это PHP Дайджест от CutCode. Давайте посмотрим, что произошло за прошедший месяц в мире PHP.
Новости PHP
Вышли PHP 8.1.29, PHP 8.2.20 и PHP 8.3.8
В этих выпусках исправлены уязвимости:
Инъекция аргументов в PHP-CGI.
Обход фильтра FILTER_VALIDATE_URL в функции filter_var.
Экранирование аргументов для bat- и cmd файлов в Windows окружении для функции proc_open.
Уязвимость к атаке Marvin функции openssl_private_decrypt.
Пожалуйста, обновитесь, как можно скорее.
PHP исполнилось 29 лет!
8 июня 1995 года Rasmus Lerdorf впервые объявил о PHP.
Рома Пронский опубликовал ролик, в котором он скомпилировал и запустил первую версию языка. Посмотрите, каким был PHP 29 лет назад.
С днем рождения, PHP! ???
Митап на Таганской
Прошел митап Beer PHP Moscow, на котором выступили с докладами про профилирование и асинхронные PHP-приложения Алексей Сидоркин (Архитектор ГК Т1), Максим Хасанов (Team lead, АльфаСтрахование) и Валентин Удальцов (автор каналов Пых и PHP Point, преподаватель Хардкорного курса PHP).
Lamoda Tech Meetup
Прошел еще один митап от команды Lamoda Tech на котором выступили Михаил Мохначёв и Константин Козин, рассказав как почти безболезненно перейти на язык Go PHP-разработчику.
Developer Ecosystem Survey 2024
Команда JetBrains запустила восьмое ежегодное исследование экосистем разработчиков, посвященное текущему состоянию индустрии разработки программного обеспечения.
Прохождение опроса не займет много времени, а JetBrains, как всегда, поделится результатами исследования.
Projects IDX
Google анонсировала свой новый инструмент онлайн-среды разработки, который поставляется с шаблоном Laravel из коробки.
В своем личном телеграм канале Данил уже поделился первыми впечатлениями, почитайте, если еще видели.
Большинство новостей ядра PHP подробно освещаются в серии PHP Core Roundup от PHP Foundation, мы лишь быстро по ним пробежимся:
✅ RFC: Add stream open functions to XML{Reader,Writer}
Niels Dossche предлагает добавить два новых метода для работы с потоком модуля XML:
XMLReader::fromStream()
XMLWriter::toStream()
? RFC: Static Constructors
Erick de Azevedo Lima предлагает добавить новый магический метод __staticConstruct, который будет вызываться автоматически при вызове статического метода.
? RFC: Static class
Paul Morris предлагает добавить новый тип класса – статический. Статический класс определяется ключевым словом static, а все методы этого класса автоматически становятся статическими. В настоящее время в PHP можно объявить статическими отдельные методы.
? RFC: Lazy Objects
Arnaud Le Blanc и Nicolas Grekas предлагают добавить ленивые объекты в PHP.
Ленивые объекты не будут инициализироваться до тех пор, пока в этом нет необходимости, например, не будет прочитано или изменено свойство объекта.
Ленивые объекты большинство пользователей не будут использовать напрямую, в первую очередь они предназначены для авторов библиотек и фреймворков.
? RFC: Deprecations for PHP 8.4
Группа авторов Niels Dossche, Gina Peter Banyard, Máté Kocsis, Tim Düsterhus, Kamil Tekiela и Jorg Sowa запустила обсуждение RFC, чтобы определить какой функционал объявить устаревшим в PHP 8.4 и удалить в PHP 9.0.
Laravel дайджест
Обновления Laravel
11.10. Allow callback to be passed to updateOrInsert() to pass different $values if the record already exists
https://github.com/laravel/framework/pull/51566
PR затрагивает QueryBuilder, прокачали метод updateOrInsert(). Описание PR начинается с проблемы.
Я думаю, вы знаете, что updateOrInsert() под капотом в себе содержит два запроса. Сперва мы ищем, есть ли такая запись. Соответственно, если есть, то делаем Update, в противном случае Insert. Но если, как в примере у автора:
$values = [
'name' => $data['name'],
'email' => $data['email'],
];
$exists = DB::table('users')->where('user_id', $user_id)->exists();
if (! $exists) {
$values['optional_column'] = $data['foobar'];
}
DB::table('users')->updateOrInsert(
['user_id' => $user_id],
$values
);
нам необходимо сделать Update полей с дополнительным условием, например, если запись существует, то набор полей будет иным. В таком случае нам придется сперва дополнительно проверить, есть ли запись. Далее на проверке уже сформировать массив и уже после вызвать этот сахар.
Казалось бы, зачем вообще всем этим заниматься? Сделай отдельные два запроса без сахара Laravel, но это не путь Laravel, поэтому прокачали метод updateOrInsert(). Вторым параметром можно теперь передать callback, который в себе будет иметь boolean-значение, есть ли уже запись в таблице, и если есть, мы можем строить дополнительные условия и формировать массив на updateOrInsert():
DB::table('users')->updateOrInsert(
['user_id' => $user_id],
function ($exists) use ($data) {
if ($exists) {
return [
'name' => $data['name'],
'email' => $data['email'],
];
}
return [
'name' => $data['name'],
'email' => $data['email'],
'optional_column' => $data['foobar'],
];
}
);
11.11. Give session ID retrieval the Laravel treatment
https://github.com/laravel/framework/pull/51732
Первый PR у нас затрагивает сессии, теперь нам не придется писать такой длинный метод getId и появился просто Id:
use Illuminate\Support\Facades\Session;
- Session::getId();
+ Session::id();
В изменениях PR видим, что Id это обертка над методом getId.
11.11. Add get, write and forget cache events
https://github.com/laravel/framework/pull/51560
В следующем PR, появились события по кэшу. В изменениях по PR, видим, что добавлен набор событий:

И соответственно в репозитории, когда сбрасываем кэш или добавляем в кэш, будут дергаться определенные события и теперь появились дополнительные возможности для отслеживания и взаимодействия.
11.11. Add before and after methods to Collection
https://github.com/laravel/framework/pull/51752
PR затрагивает коллекции. Добавлены два новых метода before и after. У нас есть коллекция, как в примере:
$collection = collect([1, 2, 3, 4, 5, 'name' => 'taylor', 'framework' => 'laravel']);
$collection->before(2) // 1
$collection->before('taylor') // 5
$collection->before('laravel') // 'taylor'
$collection->before(fn ($value) => $value > 4) // 4
$collection->before(fn ($value) => ! is_numeric($value)) // 5
$collection->before(1) // null
$collection->before('not found') // null
Благодаря методу before мы можем указать значение одного из элементов коллекции и получить предыдущее.
Например, через метод before указываем двойку — получаем предыдущее значение — единицу, указываем значение taylor, получаем пятерку. Также поддерживается и callback. After выполняет то же самое действие, только после указанного элемента.
11.11. About command improvement
https://github.com/laravel/framework/pull/51791
Простой PR, который продолжает улучшать artisan-команду about — добавили переменные timezone и locale из текущего конфига.
11.11. Add Relation::getMorphAlias()
https://github.com/laravel/framework/pull/51809
Следующий PR добавляет новый метод у класса Relation, чтобы получить alias у Morph-типа модели. Как видим просто указываем модель и получаем alias если он у нас ранее зарегистрирован.
$this->assertDatabaseHas('taskables', [
'taskable_type' => Relation::getMorphAlias(Document::class),
'taskable_id' => $mitigation->id,
'task_id' => $taskB->id
]);
11.11. Support third-party relations in model:show command
https://github.com/laravel/framework/pull/51807
PR прокачивает artisan-команду model:show (находит отношения модели). Теперь эта команда будет демонстрировать нам также third-party relations, например из пакетов.
11.11. Chop PHP extension when passed to make commands
https://github.com/laravel/framework/pull/51842
Раньше при вызове команд которые генерируют определенные классы, если указать расширение .php, то у вас будет сформирован класс с двойным расширением. Благодаря этому pull request, если вдруг и прописали расширение, то оно у нас будет тримиться.
До:
php artisan make:controller UserController.php
# Controller [app/Http/Controllers/UserController.php.php] created successfully.
После:
php artisan make:controller UserController.php
# Controller [app/Http/Controllers/UserController.php] created successfully.
11.12. Add multiply to collection
https://github.com/laravel/framework/pull/51870
PR по коллекциям, на этот раз добавили метод multiply. Что он из себя представляет? Например, у нас есть коллекция с определенным набором:
<div>
{{ $user->name }}
{{ $user->name }}
{{ $user->name }}
{{ $user->name }}
</div>
Multiply их будет дублировать и повторно пушить указанное количество раз:
@foreach($class->students->multiply(4) as $student)
<x-student :student="$student" />
@endforeach
11.12. Add multiply to collection
https://github.com/laravel/framework/pull/51870
PR добавляет в EventServiceProvider статический метод, который позволяет указывать где именно нам автоматически искать наши ивенты. И таких директорий может быть несколько. Можем указать либо строкой, либо в виде массива.
11.13. Account for long strings on new Laravel error page
https://github.com/laravel/framework/pull/51880
PR прокачивает верстку новой error page. Поправлены моменты, когда длинные строки с содержанием ошибки ломали верстку или выходили за экран на дисплеях с небольшим разрешение. Проблемы решены и error page выглядит еще лучше.
11.13. Add Support for Extensions in Str::markdown Method
https://github.com/laravel/framework/pull/51907
Следующий PR затрагивает Helper по работе со строками. Метод Markdown. Третим параметром также принимает набор extension из набора CommonMark:
public function parseMarkdownFromFile($file_location){
$markdown_contents = File::get($file_location);
$html = Str::markdown($markdown_contents, [], [
new AttributesExtension(),
new TaskListExtension(),
]);
return $html;
}
Автор PR даже снял минутный ролик о том как это работает. Как это выглядело до и как он прокачал рендер Markdown.
11.13. Update config:show command
https://github.com/laravel/framework/pull/51902
PR который прокачивает команду config:show. До этого были проблемы с отображением конфига через "dot"-нотацию. Ошибка если конфиг не найден была некорректной - теперь исправили.
11.13. Display view creation messages
https://github.com/laravel/framework/pull/51925
Следующий PR улучшил отображение информации. Раньше при создании компонента у нас отображалось, что компонент по указанному пути успешно создан, но при этом не говорилось о том, что также создана вьюха. Теперь эта проблема решена.
11.13. Introduce Str::chopStart and Str::chopEnd
https://github.com/laravel/framework/pull/51910
Прокачали Helper-класс по работе со строками, добавили несколько новых методов ChopEnd, ChopStart, ReplaceEnd и ReplaceStart. ChopEnd нам дает возможность получить значение строки до указанного выражения и аналогично ChopStar (только указываем после какого значения). Также можно передавать массив с несколькими значениями:
Str::chopEnd('path/to/file.php', '.php');
// "path/to/file"
Str::chopStart('https://laravel.com', ['https://', 'http://']);
// laravel.com
Метод replaceEnd заменяет окончание строки на указанное значение, если эта строка заканчивается на определённую подстроку. Аналогично работает ReplaceStart.
Видео-версия дайджеста:
FanatPHP
Мне кажется, список предложений по объявлению функционала устаревшим стоило добавить в текст поста. Некоторые выглядят спорно.
Formally deprecate Soft-deprecated
DOMDocumentandDOMEntitypropertiesRemove
DOMImplementation::getFeature($feature, $version)Deprecate
DOM_PHP_ERRConstantunserialize()'s 'S' tagsession.sid_lengthandsession.sid_bits_per_characterDeprecate
SplFixedArray::__wakeup()xml_set_object()andxml_set_*_handler()with string method namesPassing
nullandfalsetodba_key_split()Deprecate passing incorrect data types for options to ext/hash functions
Constants
SUNFUNCS_RET_STRING,SUNFUNCS_RET_DOUBLE,SUNFUNCS_RET_TIMESTAMPDeprecate proprietary CSV escaping mechanism
Deprecate
E_STRICTConstantDeprecate
strtok()Deprecate returning non-string values from a user output handler
Deprecate producing output in a user output handler
file_put_contents()with$dataas an arrayDeprecate
mysqli_ping()andmysqli::ping()Deprecate
mysqli_refresh()Deprecate
mysqli_kill()Deprecate the second parameter to
mysqli_store_result()Deprecate
lcg_value()Deprecate
uniqid()Deprecate
md5(),sha1(),md5_file(), andsha1_file()Deprecate passing
E_USER_ERRORtotrigger_error()Deprecate using a single underscore
_as a class nameDeprecate
SOAP_FUNCTIONS_ALLconstant and passing it toSoapServer::addFunction()qeeveex
Мне как старичку давно мигрировавшему на другой ЯП пометка deprecate
md5()очень удивила.md5 удобен для не секретных и не критичных к коллизиям местах. Он быстр и лёгкий.
Какие есть альтернативы сопоставимые по ресурсам? В т.ч. чтоб хеш не занимал больше байтов.
FanatPHP
Ну так сам алгоритм он и не предлагает убрать. А только функцию. Чтобы типа только привлечь внимание к
проблемам голодающих меньшинствпотенциальным проблемам этих алгоритмов, но при этом такой заход сбоку. В общем очередная прекраснодушная инициатива. Надеюсь, она не пройдет голосование.