Пых – 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
ML-assisted completion

Примерно с месяц у меня в PhpStorm включен бесплатный Full Line Code Completion. Если бы после обновления он не был "искаропки", я б, наверное, так и не попробовал ничего подобного. Но раз судьба свела, вот мои наблюдения.

Без помощника:
1. размышляю над тем, что написать дальше (по сути, это самый сложный и долгий этап),
2. пишу код, используя хоткеи, шаблоны и стандартный предсказуемый автокомплит.

С помощником:
1. размышляю над тем, что написать дальше,
2. ввожу пару символов, вижу на экране подсказку (иногда с запозданием),
3. зрительно анализирую её (дополнительная мыслительная деятельность),
4. с вероятностью 40% ассистент не угадывает точь-в-точь, goto 2;
5. с вероятностью 60% угадывает, нажимаю Tab.

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

Возможно, я сейчас написал какой-то ретроградский пост и мне просто нужно установить полноценный AI Assistant, тогда-то всё встанет на свои места. Или я пишу не тот код — надо меньше думать, больше формошлёпить и крудить, а не тайфуны типунить... Короче, разубедите или поддержите меня — я в этой теме новичок.
👍64💯33😁102🤔2💩1
Пых
Дмитрий Стогов одобрил мой PR! На текущий момент RFC набрал 16 голосов "за" и 2 "против".
Официально объявляю свой RFC принятым!

Не буду ждать утра, чтобы сообщить, что я только что закрыл голосование на отметке в 25 голосов против 4. Это означает, что в PHP 8.4 мы с вами сможем писать new без скобок! Осталось только дождаться мёрджа PR в мастер.

До сих пор не верится, что шальная попытка законтрибьютить в PHP, предпринятая за завтраком 26 декабря прошлого года, увенчалась успехом. Теперь есть запал для пары других идей. Попробую летом их оформить.

Всем огромное спасибо за поддержку!
🔥329👍80🎉62🤮154🌚2👎1🍾1😎1
Пых
Официально объявляю свой RFC принятым! Не буду ждать утра, чтобы сообщить, что я только что закрыл голосование на отметке в 25 голосов против 4. Это означает, что в PHP 8.4 мы с вами сможем писать new без скобок! Осталось только дождаться мёрджа PR в мастер.…
🎉 Merged!

После исправления косяка, замеченного зорким глазом Никиты Попова, мой PR был окончательно одобрен и наконец-то попал в master! У них там как-то странно это происходит — через отдельный commit и закрытый PR, хотя у меня во всех проектах на GitHub аналогичный squash + rebase по кнопке даёт фиолетовый статус "merged", а не красный "closed". Но не суть.

Тем временем я закинул в internals ещё одну идею. Я предложил вынести методы ArrayAccess::offsetExists, offsetGet в отдельный интерфейс с рабочим названием ArrayAccessRead, чтобы можно было делать иммутабельные коллекции, поддерживающие $object['key'] синтаксис только в режиме чтения. Но выяснилось, что уже есть драфт отличного RFC, который предлагает куда более глубокое переосмысление кривого ArrayAccess. Надеюсь, что он тоже попадёт в 8.4, а я пока подумаю над чем-то ещё. 🍸
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥157🎉63👍34💩5👏42👎1👀1
🍻 Пишем на 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