Telegram Web Link
Компонент или компонента фреймворка?
Anonymous Poll
94%
компонент
6%
компонента
Поиск и устранение утечек памяти в PHP с разбором реального примера

29 июля, в эту среду, в 18:00 я проведу стрим на канале PHP Point.

Примерный план:
• поговорим о видах утечек и инструментах для их поиска;
• установим один проблемный компонент Symfony и найдём в нём утечку;
• запилим быстрый фикс для проекта при помощи Compiler Pass;
• если успеем, сделаем Pull Request в репозиторий Symfony.

https://www.youtube.com/watch?v=NNMp-97rk9c
​​#MoreView #13 | Валентин Удальцов – Автор канала "Пых" и ведущий разработчик в Happy Job

Продолжаю брать интервью у людей из мира PHP. На этот раз в гостях Валентин Удальцов. Я познакомился с ним в процессе организации онлайн-собеседования PHP разработчика. После предыдущего интервью с Дмитрием Елисеевым я понял что мне интересно еще поговорить про PHP и я сразу вспомнил про следующего гостя:)

В четверг в 17.00 поговорим про PHP, архитектуру, Пых, музыку и многое другое в онлайн формате. Приходите, задавайте вопросы и выигрывайте пиццу за лучший вопрос:)

Подробнее о выпуске: amorev.ru/moreview-13-valentin-udaltsov
Ссылка на трансляцию: youtu.be/LOrb3m0FQdU
Как сделать тестируемым класс, использующий нечистую встроенную функцию PHP?

Очень просто — объявить функцию необязательным параметром конструктора.

final class Service
{
/**
* @psalm-var callable(): int
*/
private $time;

/**
* @psalm-param ?callable(): int $time
*/
public function __construct(?callable $time = null)
{
$this->time = $time ?? 'time';
}

public function do(): void
{
$time = ($this->time)();
}
}

$service = new Service();

$serviceForTesting = new Service(static fn (): int => 1234567890);


Не советую использовать либы-костыли типа php-mock/php-mock.
Через 5 минут начинаю рассказывать про утечки памяти в PHP!

Присоединяйтесь, обсудим инструменты, лайфхаки и проанализируем реальный кейс.

https://www.youtube.com/watch?v=NNMp-97rk9c
Через несколько минут я окажусь в гостях у Антона Морева на канале MoreView!

Буду ждать ваши каверзные вопросы 😅
По словам Антона, автор самого крутого вопроса получит 🍕

https://www.youtube.com/watch?v=LOrb3m0FQdU
Вчера в интервью 🎙 я умудрился в одно предложение засунуть сразу 4 баззворда:
функциональный язык, агрегат, Event Sourcing и чистые функции.

Спешу поделиться докладом, который придал мне столько смелости 🤣
У него довольно неочевидное название, но очень крутое содержание.

https://www.youtube.com/watch?v=USSkidmaS6w
Media is too big
VIEW IN TELEGRAM
После интервью ребята в нашем обсуждении предложили выяснить, как много среди нас музыкантов 🎼

За барабанами ваш покорный слуга ☺️
На прошлой неделе я провёл стрим про утечки памяти в PHP

По ссылке запись трансляции с таймкодами и разбивкой на эпизоды.

https://www.youtube.com/watch?v=NNMp-97rk9c

По результатам я предложил два изменения в Symfony, оба уже приняты:

#37705 добавить тег kernel.reset для сервиса mailer.logger_message_listener,

#37712 перенести MessageLoggerListener в конфиг mailer_debug.
time_diff_ms(DateTimeImmutable, DateTimeImmutable): int

Вчера игрался с задержками (delay) в брокерах сообщений.
Потребовалась функция для нахождения разницы между двумя метками времени в миллисекундах.

Ловите Gist с функцией и юнит-тестом 🍭

https://gist.github.com/vudaltsov/0bb623b9e2817d6ce359eb88cfbf229d
В обсуждении ребята подняли вопрос об учёте часовых поясов в функции из поста выше.

time_diff_ms() корректно учитывает временные зоны, так как сравнивает абсолютные метки времени, а не время настенных часов (wall-clock time).

Попутно мы выяснили, что метод DateTime(Immutable)::setTimezone() не изменяет абсолютное время, просто адаптирует время настенных часов под часовой пояс. Метка времени до и после setTimezone() остаётся такой же. Смотрите также комментарий к документации метода.

Добавил в Gist тесты для всех сценариев создания объекта времени.

https://gist.github.com/vudaltsov/0bb623b9e2817d6ce359eb88cfbf229d#file-time_diff_ms_test-php
Как одним выражением прочитать и изменить свойство

[$currentValue, $this->property] = [$this->property, $newValue];

Этот приём можно использовать, например, в базовом классе корня агрегата.

abstract class AggregateRoot
{
/**
* @psalm-var list<object>
*/
private array $events = [];

/**
* @psalm-return list<object>
*/
final public function releaseEvents(): array
{
[$events, $this->events] = [$this->events, []];

return $events;
}

final protected function raise(object $event, object ...$events): void
{
$this->events = [...$this->events, $event, ...$events];
}
}


Некогда подглядел у @fes0r.
Недавно узнал, что есть подход, при котором юнит-тесты кладут рядом с тестируемыми классами 🤔

Примеры:
https://github.com/thephpleague/flysystem/tree/2.x/src,
https://github.com/EventSaucePHP/EventSauce/tree/master/src/Integration.

Выглядит заманчиво — не надо синхронизировать две файловые структуры и бегать туда-сюда. И на ревью сразу видно, написан тест для нового класса или нет. Также этот подход должен повысить мобильность модулей кода — модуль не надо собирать по папкам src и test, чтобы переименовать или вынести в Composer-пакет.

В библиотеках такие тесты легко удалить из архива правилом **/*Test.php export-ignore в .gitattributes. Проект можно аналогичным образом чистить перед деплойментом.

Что думаете? Приглашаю обсудить в Пыхтелку 🐯
Отличная статья про именованные агрументы от автора Psalm Мэтта Брауна!

В ней рассказывается про нюансы использования именованных аргументов в PHP 8 и про то, как новая версия Psalm 3.14.0 поможет их снивелировать.

https://psalm.dev/articles/getting-ready-for-named-arguments
Оказывается, для Symfony уже давно есть Psalm-плагин 😮

На радостях сделал 5 пулл-реквестов на базе стабов, которые мы скопили на рабочем проекте. Все 5 были приняты и вошли в релиз 1.4.3 ☺️

Кто до сих пор не использует статический анализ, советую просмотреть мои PR. Приёмочные тесты дадут вам некоторое представление о том, как статический анализ может вывести типизацию привычных инструментов на новый уровень.

https://github.com/psalm/psalm-plugin-symfony
2025/07/09 12:55:41
Back to Top
HTML Embed Code: