Пых – Telegram
Пых
8.27K subscribers
260 photos
14 videos
6 files
566 links
Блог Валентина Удальцова о разработке на PHP.

Хобот @phpyhobot
https://youtube.com/@phpyh
https://vkvideo.ru/@phpyh
https://news.1rj.ru/str/isPHPdying

Статистика: https://news.1rj.ru/str/INOTAROBOT?start=st1219340804

Для связи используйте личные сообщения канала.
Download Telegram
В обсуждении ребята подняли вопрос об учёте часовых поясов в функции из поста выше.

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
Forwarded from PHP Digest
Открытое собеседование по PHP | Эпизод #2 — Прием заявок

Пилотный выпуск открытого собеседования зашел отлично, и мы получили много ценных отзывов. Спасибо всем, кто был с нами на стриме и задавал вопросы!

Если вдруг вы не видели первый выпуск, то вот запись https://www.youtube.com/watch?v=FQNd9W3nb3A

Тем временем начинаем подготовку второго выпуска!

Требования для участия не поменялись:
• уровень middle/senior;
• PHP 7.x, PSR;
• ООП, SOLID, coupling/cohesion, вот это все;
• тестирование, PHPUnit;
• желателен опыт с Symfony 4/5;
• SQL, желательно PostgreSQL;
• представление о современных трендах в архитектуре приложений.

Темы будут ± те же, а вот вопросы подготовим новые, без Psalm 🙂

Заявку на участие можно отправить до 27 августа через форму: https://forms.gle/ES3nXiwf4ycosGEy9.

Вопросы в личку: @vudaltsov, @pronskiy.
Раньше, чтобы создать nullable ValueObject из nullable примитива, приходилось писать колбасу вроде

null === $stringClientId ? null : ClientId::fromString($stringClientId)
.

Сегодня условные типы Psalm позволяют перенести if в статический конструктор:

/**
* @template T of ?string
* @psalm-param T $id
* @psalm-return (T is null ? null : self)
*/
public static function fromString(?string $id): ?self
{
if (null === $id) {
return null;
}

Assert::uuid($id);

return new self($id);
}

ClientId::fromString($stringClientId)


https://psalm.dev/r/ab0090be4c
Рекомендую доклад Temporal Modeling.

Mathias Verraes демонстрирует, как моделировать поведение через события и процессы, а не структуры данных и состояние. Такой подход повышает эффективность взаимодействия с бизнесом и позволяет ещё на этапе обсуждения выявить больше нюансов предметной области.

https://youtu.be/hh5lskgATCk

Список всех докладов Матиаса на эту тему
> Вам нужны условия Йоды только если ваши тесты 💩 и вы думаете, что перестановка аргументов сравнения имеет большее значение, чем корректная запись ваших бизнес-правил.

https://twitter.com/frankdejonge/status/1298602389281411072

Мы используем в проекте условия Йодыфиксер yoda_style), но этот твит заставил меня задуматься, зачем 🤣

Когда-то давно я бы ответил "потому что так в Symfony Coding Standards", позже "потому что так удобнее присваивать результат сравнения", сегодня "только потому что привык".
Используете ли вы условия Йоды?
Anonymous Poll
32%
да
68%
нет
Пояснение к моей задаче на канале PHP задачи с собеседований.

Метод __get() выполняется при попытке чтения из недоступных (защищённых или приватных) или несуществующих свойств. Публичное неинициализированное типизированное свойство таковым не является.

Интересно, что вызов магических методов для неинициализированных свойств изначально был предусмотрен в RFC: Typed Properties 2.0 и имплементирован в 7.4.0. Однако после обсуждения различных WTF кейсов этот функционал был удалён в 7.4.1.

Чтобы всё-таки стриггерить __get, __set, __isset или __unset для типизированного свойства, необходимо сначала "удалить" его через unset: https://3v4l.org/RbFFM.

Пара статей про ленивую инициализацию свойств:
https://ocramius.github.io/blog/intercepting-public-property-access-in-php/,
https://ocramius.github.io/blog/lazy-property-automatic-property-initialization/.
Наброски системы плагинов для Infection от @ocramius

https://github.com/infection/infection/issues/1323

Пример того, как надо оформлять RFC issue в проектах с открытым исходным кодом 👍

Кстати, интересно, что тикеты в Infection (фреймворк Максима Рафалко для мутационного тестирования) уже не в первый раз становятся источником знаний и вдохновения для PHP сообщества 🔥

Также смотрите треды в Twitter на эту тему:
https://twitter.com/Ocramius/status/1302886222747119616,
https://twitter.com/slamzoe/status/1302909388894724101.
Полезная задачка про json_encode в PHP 7.4 от меня на канале PHP задачи с собеседований.

https://news.1rj.ru/str/phpquiz/309
Вспомнил, что ещё в декабре мы горячо обсуждали этот нюанс в чате @symfony_php.

В результате прений я сделал Pull Request, который привёл в соответствие поведение Symfony Serializer.

https://github.com/symfony/symfony/pull/34791
Какая у тебя ЗП в тысячах рублей?
Дудь, разлогинься 😂
Final Results
15%
<50
25%
50-100
21%
100-150
16%
150-200
9%
200-250
4%
250-300
2%
300-350
1%
350-400
1%
400-450
4%
>450
Ищу к себе в команду middle PHP-разработчика

В Happy Inc мы исследуем вовлечённость и лояльность персонала в крупных компаниях. По-простому — собираем данные и строим отчёты. Но всё это приправлено многогранной бизнес-логикой, сложной авторизацией и прочими ноу-хау.

PHP 7.4 / Symfony 5.1 / PostgreSQL 12 / OpenAPI / CQRS / ES / DDD / Psalm на максималках и всё, о чём я тут рассказываю 😜

Full-time, Москва, БЦ Варшавка Sky, ЗП по результатам собеса.

https://happy-job.ru/vacancy-super-php-2020-10

Резюме можно присылать сразу мне @vudaltsov.
Сегодня ребята в Пыхтелке активно обсуждают JWT vs Server Side Sessions, поддерживаю разговор мыслями и ссылками.

• Сессии — это абсолютно валидный, неустаревший подход. Не стоит переписывать аутентификацию из-за хайпа вокруг JWT.
• Сессии усложняют горизонтальное масштабирование, но так ли остро стоит этот вопрос в вашем проекте?
Стандарт JWT действительно несовершенен, история помнит несколько серьёзных уязвимостей в его реализациях. Но в 2020 это не так актуально, просто проверьте, что вы обновили библиотеки.
• JWT не предусматривает простого механизма инвалидации токена. Либо придётся выставлять короткий Expiration Time, либо строить сложный statefull механизм для гибкого контроля выданных токенов.
• JWT удобен для организации временного ограниченного доступа к конкретным операциям/ресурсам: эндпойнтам API, файлам, действиям по ссылкам из персонализированных рассылок.
⚠️ Небольшое сообщение для тех, кто обновил Symfony до 4.4.14 / 5.1.6

Обратите внимание, что рядом с вашим src/Kernel.php появился автогенерируемый файл .preload.php (#38140, #38142, документация).

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

Спасибо @Taarim за наводку 😊