Всем привет!

Это 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 лет назад.

Running PHP 1.0 in 2024

С днем рождения, 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.

Видео-версия дайджеста:

Комментарии (3)


  1. FanatPHP
    11.07.2024 08:09
    +6

    Мне кажется, список предложений по объявлению функционала устаревшим стоило добавить в текст поста. Некоторые выглядят спорно.

    • Formally deprecate Soft-deprecated DOMDocument and DOMEntity properties

    • Remove DOMImplementation::getFeature($feature, $version)

    • Deprecate DOM_PHP_ERR Constant

    • unserialize()'s 'S' tag

    • session.sid_length and session.sid_bits_per_character

    • Deprecate SplFixedArray::__wakeup()

    • xml_set_object() and xml_set_*_handler() with string method names

    • Passing null and false to dba_key_split()

    • Deprecate passing incorrect data types for options to ext/hash functions

    • Constants SUNFUNCS_RET_STRINGSUNFUNCS_RET_DOUBLESUNFUNCS_RET_TIMESTAMP

    • Deprecate proprietary CSV escaping mechanism

    • Deprecate E_STRICT Constant

    • Deprecate 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 array

    • Deprecate mysqli_ping() and mysqli::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(), and sha1_file()

    • Deprecate passing E_USER_ERROR to trigger_error()

    • Deprecate using a single underscore _ as a class name

    • Deprecate SOAP_FUNCTIONS_ALL constant and passing it to SoapServer::addFunction()


    1. qeeveex
      11.07.2024 08:09
      +2

      Мне как старичку давно мигрировавшему на другой ЯП пометка deprecate md5() очень удивила.
      md5 удобен для не секретных и не критичных к коллизиям местах. Он быстр и лёгкий.

      Какие есть альтернативы сопоставимые по ресурсам? В т.ч. чтоб хеш не занимал больше байтов.


      1. FanatPHP
        11.07.2024 08:09
        +1

        Ну так сам алгоритм он и не предлагает убрать. А только функцию. Чтобы типа только привлечь внимание к проблемам голодающих меньшинств потенциальным проблемам этих алгоритмов, но при этом такой заход сбоку. В общем очередная прекраснодушная инициатива. Надеюсь, она не пройдет голосование.