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

Хобот @phpyhobot
https://youtube.com/@phpyh
https://vkvideo.ru/@phpyh
https://t.me/isPHPdying

Статистика: https://t.me/INOTAROBOT?start=st1219340804

Для связи используйте личные сообщения канала.
Download Telegram
🍻 Пишем на PHP и не теряем память. It even works underwater!

В этот четверг в 19:00 на Автозаводской Таганке пройдёт митап BeerPHP, посвящённый производительному PHP.

Максим Хасанов расскажет про RoadRunner, Алексей Сидоркин про Swoole, а у меня будет секция про память. Обсудим, откуда берутся утечки и как подготовить код для запуска в неумирающих рантаймах.

Только оффлайн, без трансляции и записи. Если ты в Москве, регистрируйся и приходи!

https://beerphp.ru/
Please open Telegram to view this post
VIEW IN TELEGRAM
😢73👍35👎21😡112
🐘 С днём рождения, PHP!

К 29-ому дню рождения PHP Рома Пронский опубликовал ролик, в котором он скомпилировал и запустил первую версию языка!

https://youtu.be/0BPExYh5Anw

И ещё несколько ссылок для любознательных:
интервью с Расмусом про то, как он изобрёл PHP,
статья Артёма Украинского про PHP 1 на Хабре,
музей PHP.
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉80👍18🔥9👎2
📹 Стримкаст про типы в PHP

Завтра (12 июня) в 20:00 встретимся с Димой Елисеевым на новом канале Станислава Ракчаева и команды LivePHP "Абстрактный программист", чтобы обсудить типизацию. Ребята подкупили меня фразой "затронем Typhoon". 😂

В общем, заходите, задавайте вопросы, расскажу всё, что знаю.

https://youtu.be/eXfsU-x3bMg

P.S.: Видео с прошедшего BeerPHP обязательно будет, но нужно ещё подождать.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43🔥20
Разбор резюме от Егора Бугаенко

https://youtu.be/af6bidlat6Q

Прям очень зашло! Когда снова буду искать работу, обязательно переделаю резюме.

Мои заметки:
• свой документ вместо типовой выгрузки с HH,
• две версии анкеты: сжатая и яркая для технаря, подробная и скучная для HR,
• убрать подработки верстальщиком в интернет-магазине в студенческие времена,
• уникальный опыт на каждом месте работы (так-то все мы рефакторим, пилим фичи и тестируем),
• каждый факт должен подтверждаться ссылкой.

Понравилась следующая мысль. Если я, например, указываю в резюме "Git" и "Symfony 6", то я лукавлю, потому что это неравноценные навыки. Я никогда не просматривал исходники гита, не делал про него докладов, тем более не контрибьютил. Да, я умею в rebase, знаю разные flow, но это само собой разумеется. В то же время у меня суммарно под сотню PR и issue в symfony/symfony, я выступал на SymfonyCon, лично знаком с Core-командой и читаю курс с использованием этого фреймворка. Принципиально другой уровень! Так что в версии резюме для технаря "Git" я уж точно уберу.
👍39🔥13👎11🤡6
Пых
BeerPHP сменил локацию! Митап пройдёт в лофте "Событие" на Таганке. Организаторы говорят, что эта площадка значительно лучше. Дата и время те же самые: 6 июня (завтра) в 19:00. Также мне разрешили поделиться с вами записью доклада после мероприятия! ht…
📹 BeerPHP. Пишем на PHP и не теряем память

Наконец-то мы смонтировали ролик! Помимо доклада в нём есть признание в любви к вам, матерные слова и подробная история моего RFC.

Получилось очень задорно! Спасибо организаторам и участникам BeerPHP за такую крутую атмосферу.

https://youtu.be/56I5C0NYjv8
https://vudaltsov.github.io/memory-leaks-slides/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍70🔥326🥰1🌭1
🎵 Музыкальный стрим!

Хотите музыкальный стрим сегодня с 17 до 18 МСК? Позже, к сожалению, не получится из-за договорённостей с соседями. Сыграю несколько песен на барабанах (можно будет даже заказать), отвечу на ваши вопросы. Посмотрим, что из этого выйдет. 😉

Ставь 🤩, если заглянешь.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩51🔥14👍13👎73😁2
🎙 PHP Russia 2024 быть!

28 и 29 ноября в Москве пройдёт конференция Highload, в рамках которой 16 докладов будут выделены под PHP Russia.

Наилучший способ туда попасть — выступить! Плюшки спикера: куратор из программного комитета для подготовки крутого доклада (например, я), транспорт до Москвы и комфортное проживание, бейдж с полным доступом ко всем залам и зонам Highload. А ещё спикер навсегда вписывает себя и свои идеи в историю PHP. Короче, грех не податься!

Дай угадаю. Если ты раньше не выступал, то сейчас думаешь: "Ой, ну мне не о чем рассказывать, у нас всё стандартно." Поверь, так не бывает! У каждой компании есть ноу-хау, иначе она была бы неприбыльной и ты работал бы в другой. А раз "every company is a software company", то ноу-хау должно быть и в софте. Твоя задача — найти его и заполнить форму. Ещё можно предложить доклад про это самое "стандартно" и как его правильно готовить. Дальше мы уже решим, что впишется в программу, а что нет.

Итак, темы этого года:
• FFI, практическое применение
• AI/ML + PHP
• Производительность
• Devops под PHP
• Лучшие практики
• Новые крутые либы
• Альтернативные рантаймы
• Новые фреймворки
• Опыт больших сложных проектов на PHP

Ждём твой доклад по адресу https://cfp.phprussia.ru/ до 2-ого сентября.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51🔥25🤮5💩2
Александр Кирсанов, руководитель команды KPHP, ушёл из ВК

https://vk.com/@kphp-all

Буду ждать от Саши новых проектов для PHP!

Ребят, я тут затайфунился жёстко. Скоро снова выйду в свет. Куча идей постов, стримов и, конечно, новый поток курса. Просто нужно ещё немного времени. Всех люблю!
🫡79👍149💩7🔥4🗿4🤔3
💙 Typhoon 0.4.0

https://github.com/typhoon-php/typhoon/releases/tag/0.4.0

Вчера ночью, ровно через 5 месяцев после 0.3.0, поставил следующий минорный тег. По сути, он, конечно, мажорный, так как 0.y релизы могут ломать обратную совместимость, чем мы не преминули многократно воспользоваться. 😈 С этой версии будем вести Changelog, так как капитальных переписываний в ближайшее время не ожидается.

Это был долгий, но полный важных осознаний путь. В цикле постов расскажу про каждое.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥29🎉10👍2
Пых
💙 Typhoon 0.4.0 https://github.com/typhoon-php/typhoon/releases/tag/0.4.0 Вчера ночью, ровно через 5 месяцев после 0.3.0, поставил следующий минорный тег. По сути, он, конечно, мажорный, так как 0.y релизы могут ломать обратную совместимость, чем мы не преминули…
💙 Typhoon 0.4. Тип not

Как вы наверняка знаете, в Psalm и PHPStan есть типы non-empty-string, non-empty-list<TValue> и non-empty-array<TKey, TValue>. В далёкой 0.2 версии тайфуна они обрабатывались индивидуально — у каждого был свой метод в TypeVisitor. Затем в 0.3 мы попытались сократить избыточность, внедрив конструктор non-empty<T>, но не покидало ощущение, что это костыль. И, наконец, месяц назад пришло осознание, что нужен конструктор не для непустоты, а для отрицания.

В самом деле, выведем статически типы внутри вот такой функции:


/**
* @template T
* @param T $bar
*/
function foo(mixed $bar): void
{
if (is_string($bar)) {
// тут у $bar тип T & string

return;
}

// а тут у $bar тип T & !string

trim($bar); // ошибка: ожидается string
}


Очевидно, что для статического анализатора отрицание может быть очень полезно. В TypeScript был такой PR, но почему-то заглох. Psalm и PHPStan частично поддерживают ! в аннотациях @assert:


/**
* @psalm-assert !null $value
* @phpstan-assert !null $value
*/
function assertNotNull($value): void
{
if ($value === null) {
throw new InvalidArgumentException();
}
}


Ну а в typhoon/type 0.4 not теперь first-class тип. Семейство non-empty-*, а заодно и non-falsy-string выражаются так:


non-empty-string = string & !''
non-falsy-string = truthy-string = non-empty-string & !'0'
non-empty-list<TValue> = list<TValue> & !array{}
non-empty-array<TKey, TValue> = array<TKey, TValue> & !array{}

Здесь array{} — это запечатанный array-shape без элементов, то есть []. Его ещё часто пишут как array<never, never>.


Чтобы обойти types::nonEmptyString через TypeVisitor, достаточно смаршрутизировать его как пересечение с соответствующими аргументами:


enum types implements Type
{
// ...
case nonEmptyString;

public function accept(TypeVisitor $visitor): mixed
{
return match ($this) {
// ...
self::nonEmptyString => $visitor->intersection($this, [
self::string,
self::not(self::string('')),
]),
}
}
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥161👎1🤯1
Пых
💙 Typhoon 0.4.0 https://github.com/typhoon-php/typhoon/releases/tag/0.4.0 Вчера ночью, ровно через 5 месяцев после 0.3.0, поставил следующий минорный тег. По сути, он, конечно, мажорный, так как 0.y релизы могут ломать обратную совместимость, чем мы не преминули…
💙 Typhoon 0.4. self, parent, static

В документации PHP self, parent и static называются относительными типами классов (relative class types). С этой троицей мы боремся с самого начала. Каждый релиз — новый раунд.

Раунд 1

Возьмём пару классов:


class A extends stdClass
{
public function self(): self { return $this; }
public function parent(): parent { return $this; }
public function static(): static { return $this; }
}

final class B extends A {}


С self и parent здесь всё просто и однозначно: в классе A self = A, parent = stdClass, в класс B копируем эти 2 метода с уже разрешёнными типами A и stdClass. Значит, self и parent можно не оформлять как самостоятельные типы, а сразу заменять на конкретные классы из скоупа.

Можем ли мы так же разрешить static? Нет, так как это имя не текущего, а вызываемого класса (см. позднее статическое связывание): в A static резолвится как A, а в B — как B. При построении рефлексии мы должны в каждом унаследованном методе обновить static с учётом текущего скоупа. Для этого замоделируем static как first-class тип, который знает, где он сейчас находится, и получим typhoon/type 0.2:


A,B::self() возвращают types::object(A::class)
A,B::parent() возвращают types::object(stdClass::class)
A::static() возвращает types::static(A::class)
B::static() возвращает types::static(B::class)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥2😐1
Пых
💙 Typhoon 0.4. self, parent, static В документации PHP self, parent и static называются относительными типами классов (relative class types). С этой троицей мы боремся с самого начала. Каждый релиз — новый раунд. Раунд 1 Возьмём пару классов: class A…
💙 Typhoon 0.4. self, parent, static.

В Typhoon 0.3 я начал добавлять поддержку трейтов. И всё, естественно, поломалось. 🙈

Раунд 2


trait T
{
public function self(): self { return $this; }
public function parent(): parent { return $this; }
public function static(): static { return $this; }
}


Валидный ли это код? Да. Вот только ни один из трёх типов невозможно отрезолвить так же, как мы это делали выше. self и parent не на что заменить, так как трейт сам по себе не является типом и не может наследовать другие. Для static отсутствует скоуп-класс.

Нативная рефлексия, кстати, вообще не парится: всегда возвращает ReflectionNamedType с 'self', 'parent' или 'static'. Мы так делать не хотим, потому что это просто откладывание проблемы на потом.

Постепенно приходит понимание, что в трейтах относительные типы работают как плейсхолдеры. В Psalm и PHPStan их даже можно ограничивать через аннотации @require-extends и @require-implements. Всё это напоминает... дженерики!

Действительно,


/**
* @psalm-require-extends stdClass
* @phpstan-require-extends stdClass
*/
trait T
{
public function self(): self { return $this; }
public function parent(): parent { return $this; }
public function static(): static { return $this; }
}

final class A extends stdClass
{
use T;
}


можно с натяжкой переписать как


/**
* @template self of object
* @template parent of stdClass
* @template static of self
*/
trait T
{
public function self(): self { return $this; }
public function parent(): parent { return $this; }
public function static(): static { return $this; }
}

final class A extends stdClass
{
/**
* @use T<self, parent, self>
*/
use T;
}


Выглядит логично, но кривовато, потому что в реальности это не объявленные пользователем дженерики, а какие-то встроенные, да ещё и доступные в статике. Тем не менее, на тот момент идея мне очень нравилась, и, подставив пару костылей, я её реализовал в typhoon 0.3 и даже гордо рассказал про это на Стачке:


types::template('self', types::atClass(T::class))
types::template('parent', types::atClass(T::class))
types::template('static', types::atClass(T::class))
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🔥6😐1
Пых
💙 Typhoon 0.4. self, parent, static. В Typhoon 0.3 я начал добавлять поддержку трейтов. И всё, естественно, поломалось. 🙈 Раунд 2 trait T { public function self(): self { return $this; } public function parent(): parent { return $this; } public…
💙 Typhoon 0.4. self, parent, static

Есть у меня одна черта: я периодически возвращаюсь ко всем своим костылям, пока не сделаю нормально или не уволюсь. О том, что для относительных типов не стоит использовать дженерики, кричали разные куски кода, но всегда казалось, что будет слишком жирно делать их first-class. А потом я задумался над тем, как работают с этими типами анонимные функции.

Раунд 3


final class A extends ArrayObject
{
public function self() { return fn (): self => new self(); }
public function parent() { return fn (): parent => new parent(); }
public function static() { return fn (): static => new static(); }
}

final class B extends stdClass {}

$self = (new A())->self();
echo $self()::class; // A
echo $self->call(new B)::class; // B

$parent = (new A())->parent();
echo $parent()::class; // ArrayObject
echo $parent->call(new B)::class; // stdClass

$static = (new A())->static();
echo $static()::class; // A
echo $static->call(new B)::class; // B


Получается, что self, parent и static отлично себя чувствуют в анонимных функциях и, как и в трейтах, резолвятся в зависимости от скоупа, в том числе поддерживают его изменение в рантайме. Посмотрев на этот сниппет, мы наконец-то согласились, что относительные типы класса везде в PHP ведут себя логично и единообразно и должны быть замоделированы как first-class типы.

Теперь в typhoon/type 0.4 можно создавать self, parent и static с классом скоупа и без него. Последнее как раз требуется в трейтах и непривязанных анонимных функциях. В TypeVisitor каждый относительный тип обрабатывается индивидуально. Ну и, конечно, поддерживаются аргументы типов (а-ля self<X, Y>). Комбо-пример:


trait T
{
/**
* @return array{self, parent, static}
*/
public function types(): array
{
return [$this, $this, $this];
}
}

abstract class A extends stdClass
{
use T;
}

final class B extends A {}

$type = TyphoonReflector::build()
->reflectClass(B::class)
->methods()['types']
->returnType();

echo stringify($type);

// array{self@A, parent@stdClass, static@B}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥3🤔2
👨‍🏫 Хардкорный курс PHP, 4-й поток

Традиционно после 0.X релиза Typhoon я запускаю X-й поток курса! Сегодня X = 4.

Набор на четвёртый поток будет осуществляться как обычно. Завтра (в среду, 7 августа) в 15:00 по Москве на канале Пых появится ссылка на срез знаний. Необходимо его пройти, чтобы попасть на курс. При проверке я сначала отберу анкеты с правильными ответами, а затем отранжирую их по времени. Удачи!

Обновлённая страничка курса: hardcorephp.ru
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥36👍165🥱3😢1
Пых
👨‍🏫 Срез знаний для 4-го потока Хардкорного курса PHP! https://forms.gle/PFvHT7vujHEPuSs29 Удачи! 😉️️️️️️
🤨 Задачка со звёздочкой

Теперь, когда первая сотня абитуриентов прислала анкеты, предлагаю всем подумать над внеконкурсным заданием. Решите 5-ю задачу с теми же вводными в обратную сторону. То есть у вас должен получиться класс, который, наоборот, позволит использовать Psr\Middleware как Symfony\Subscriber. Идеи можно обсуждать в комментариях к этому посту. Позже всё разберём на стриме.

Gist с полной формулировкой этого варианта задачи: https://gist.github.com/vudaltsov/dc4f372692d2eabbc8c3d29cd4de0ccd

Навеяно, кстати, весьма драматическими событиями. В 2018-м году сообщество Symfony активно обсуждало невыполнение PHP-FIG своей "framework interoperability" миссии, так как компоненты HttpFoundation и HttpKernel нельзя малой кровью адаптировать под PSR-7. Апогеем стал pull-request Фабьена "Remove Symfony" в PHP-FIG. Тогда же у Symfony появился никому не нужный альтернативный набор контрактов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82🔥2
Пых
🤨 Задачка со звёздочкой Теперь, когда первая сотня абитуриентов прислала анкеты, предлагаю всем подумать над внеконкурсным заданием. Решите 5-ю задачу с теми же вводными в обратную сторону. То есть у вас должен получиться класс, который, наоборот, позволит…
🎉 Под занавес дня задача поддалась!

Сначала Вадим верно подметил, что суть решения сводится к приостановке потока управления внутри Middleware и предложил использовать для этого генераторы. Затем Александр скинул прототип на базе файберов.

Ну а вот полное решение с использованием Fiber и WeakMap, которое я зафиксировал вскоре после публикации задачи: код, 3v4l. Обсудим подробнее на разборе среза знаний!

P.S.: Всем спокойной ночи!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22👍103🤮1
Benchmarking Laravel with Swoole, FrankenPHP, RoadRunner, php-fpm, and ngx-php

https://youtu.be/ZB129Tjkas8
https://github.com/pronskiy/ngx-php_laravel

Позавчера Рома Пронский выложил новый ролик, в котором он забенчмаркал запуск Laravel через основные популярные рантаймы (php-fpm, RoadRunner, Swoole, FrankenPHP) + малоизвестный проект ngx-php, который по результатам Web Framework Benchmarks оставляет позади даже Swoole и workerman.
👍21🔥167