Всем привет!
Это 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
DOMDocument
andDOMEntity
propertiesRemove
DOMImplementation::getFeature($feature, $version)
Deprecate
DOM_PHP_ERR
Constantunserialize()
's 'S' tagsession.sid_length
andsession.sid_bits_per_character
Deprecate
SplFixedArray::__wakeup()
xml_set_object()
andxml_set_*_handler()
with string method namesPassing
null
andfalse
todba_key_split()
Deprecate passing incorrect data types for options to ext/hash functions
Constants
SUNFUNCS_RET_STRING
,SUNFUNCS_RET_DOUBLE
,SUNFUNCS_RET_TIMESTAMP
Deprecate proprietary CSV escaping mechanism
Deprecate
E_STRICT
ConstantDeprecate
strtok()
Deprecate returning non-string values from a user output handler
Deprecate producing output in a user output handler
file_put_contents()
with$data
as 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_ERROR
totrigger_error()
Deprecate using a single underscore
_
as a class nameDeprecate
SOAP_FUNCTIONS_ALL
constant and passing it toSoapServer::addFunction()
qeeveex
Мне как старичку давно мигрировавшему на другой ЯП пометка deprecate
md5()
очень удивила.md5 удобен для не секретных и не критичных к коллизиям местах. Он быстр и лёгкий.
Какие есть альтернативы сопоставимые по ресурсам? В т.ч. чтоб хеш не занимал больше байтов.
FanatPHP
Ну так сам алгоритм он и не предлагает убрать. А только функцию. Чтобы типа только привлечь внимание к
проблемам голодающих меньшинствпотенциальным проблемам этих алгоритмов, но при этом такой заход сбоку. В общем очередная прекраснодушная инициатива. Надеюсь, она не пройдет голосование.