Пых
Окей, ребята, я вас услышал: цена получилась слишком высокой. Для понимания: это не я решил разбогатеть — это комиссия Озона такая большая (больше трети с каждой продажи).
И сейчас до меня дошло, что те услуги, за которые Озон берёт такой процент, мне вобщем-то не нужны — я могу продавать вам из рук в руки.
Дайте мне несколько дней, я попробую автоматизировать продажи слоников с доставкой через Хобота. Кто заказал — можете отменить.
И сейчас до меня дошло, что те услуги, за которые Озон берёт такой процент, мне вобщем-то не нужны — я могу продавать вам из рук в руки.
Дайте мне несколько дней, я попробую автоматизировать продажи слоников с доставкой через Хобота. Кто заказал — можете отменить.
❤36👍26🔥13🤮4
Наполнение списка при деструктуризации
Иногда из функции надо вернуть кортеж (иммутабельную группу значений), а в DTO смысла нет, потому что это разовая ситуация и непубличное апи.
В этом случае я всегда использую запечатанный list shape, потому что его очень удобно разбирать в переменные при помощи синтаксиса деструктуризации массива:
Сейчас мне потребовалось в цикле раскидать возвращаемые методом значения по двум спискам. Приятно удивился, что при деструктуризации можно использовать не только
Упрощённый пример:
PHPStan | Psalm
Иногда из функции надо вернуть кортеж (иммутабельную группу значений), а в DTO смысла нет, потому что это разовая ситуация и непубличное апи.
В этом случае я всегда использую запечатанный list shape, потому что его очень удобно разбирать в переменные при помощи синтаксиса деструктуризации массива:
[$a, $b] = $tuple.Сейчас мне потребовалось в цикле раскидать возвращаемые методом значения по двум спискам. Приятно удивился, что при деструктуризации можно использовать не только
[$array['key']] = , но и [$array[]] =.Упрощённый пример:
interface Thing
{
/**
* @return list{int, string}
*/
public function resolve(): array;
}
/**
* @param iterable<Thing> $things
*/
function app(iterable $things): void
{
$ints = [];
$strings = [];
foreach ($things as $thing) {
[$ints[], $strings[]] = $thing->resolve();
}
var_dump($ints, $strings);
}
PHPStan | Psalm
🔥65👍37😱16👎5👀4❤2
Нюансы вариадических функций
Копаясь в статанализе в рамках проекта Typhoon, мы про каждую мелочь стараемся думать во всей полноте, чтобы не упустить даже очень редко используемые возможности PHP. Так мы периодически узнаём что-то новое.
Например, есть тип
1. Параметры, передаваемые по ссылке, очевидно, могут иметь значение по умолчанию.
2. Вариадические, очевидно, не могут иметь значения по умолчанию.
3. Могут ли вариадики передаваться по ссылке? Вот тут лично для меня уже неочевидно, потому что я вообще редко что-то передаю по ссылке.
Разбираемся. Вариадические функции добавил Никита Попов в далёком 2013 году (до этого все использовали
Пробуем:
Получается, в параметрах типа
Кстати, обратите внимание: слово "опциональный" не является точным определением для
Копаясь в статанализе в рамках проекта Typhoon, мы про каждую мелочь стараемся думать во всей полноте, чтобы не упустить даже очень редко используемые возможности PHP. Так мы периодически узнаём что-то новое.
Например, есть тип
callable(<params>): <return type>. У параметров есть следующие модификаторы: = (со значением по умолчанию), ... (вариадический), & (передаётся по ссылке). Вопрос: как их можно сочетать?1. Параметры, передаваемые по ссылке, очевидно, могут иметь значение по умолчанию.
2. Вариадические, очевидно, не могут иметь значения по умолчанию.
3. Могут ли вариадики передаваться по ссылке? Вот тут лично для меня уже неочевидно, потому что я вообще редко что-то передаю по ссылке.
Разбираемся. Вариадические функции добавил Никита Попов в далёком 2013 году (до этого все использовали
func_get_args()), и вот что написано в RFC:By-reference capture
The new syntax additionally adds support for capturing variadic arguments by-reference, something that was previously not possible in userland code. Only internal functions could make use of this viaZEND_ACC_PASS_REST_BY_REF.
This would allow implementing functions likesscanf()ormysqli_stmt::bind_param()in userland.
A by-reference capture of variadic arguments is indicated by a&before the ellipsis....
Пробуем:
function increment(int &...$ints): void
{
foreach ($ints as &$int) {
++$int;
}
}
$a = 0;
$b = 100;
increment($a, $b);
var_dump($a, $b); // 1, 101
Получается, в параметрах типа
callable возможны только два сочетания: &... и &=.Кстати, обратите внимание: слово "опциональный" не является точным определением для
= параметра. Опциональные параметры — это те, которые можно не передавать, к ним относятся не только параметры со значением по умолчанию, но и вариадические. Поэтому = однозначно определяется именно как параметр со значением по умолчанию (у нас в коде bool $hasDefault, а не $isOptional). Этот нюанс хорошо прослеживается в нативной рефлексии:
$reflection = new ReflectionParameter('increment', 'ints');
var_dump(
$reflection->isOptional(), // true
$reflection->isDefaultValueAvailable(), // false
);
👍31🔥13😨10❤5
Typhoon учится выводить дженерики
Всю неделю контрибьютил в алгебру типов Typhoon (пока в приватном репо), в частности научился программно решать системы линейных уравнений над типами.
На скриншоте вы видите, как алгебра выводит результат вызова полиморфной функции а-ля
Аналогичный код в PHPStan (выводит верно, но с нерелевантными ошибками) и Scala.
Дальше больше...
Примечание: PHPDoc просто для понимания описываемой сигнатуры, он никак не парсится алгеброй.
Всю неделю контрибьютил в алгебру типов Typhoon (пока в приватном репо), в частности научился программно решать системы линейных уравнений над типами.
На скриншоте вы видите, как алгебра выводит результат вызова полиморфной функции а-ля
array_combine. Причём делает это с анонимной сигнатурой буквально "на весу".Аналогичный код в PHPStan (выводит верно, но с нерелевантными ошибками) и Scala.
Дальше больше...
Примечание: PHPDoc просто для понимания описываемой сигнатуры, он никак не парсится алгеброй.
🔥30👍15🥴8⚡4❤🔥2🤯2😱2❤1
Два простых правила
Вот сколько лет я ни пишу код, без конца убеждаюсь в двух вещах:
1. Если стоит выбор между мутабельностью и иммутабельностью — без раздумий выбирай иммутабельность.
2. Если стоит выбор между наследованием и композицией — без раздумий выбирай композицию.
Каждый раз, когда я выбираю мутабельность, я получаю хрупкую программу с непредсказуемыми сайд-эффектами.
Каждый раз, когда я выбираю наследование, я получаю запутанный код, который трудно переиспользовать (хотя обещали, что будет наоборот) и невозможно читать, не прыгая по нескольки классам с полузащищённым API.
Интересно, что и мутабельность, и наследование осложняют типизацию и привносят костыли:
Я не Егор Бугаенко и не утверждаю, что мутабельность и наследование прям вот совсем не нужны. Но если есть выбор (90% случаев на моей open source практике) — советую воздерживаться.
Вот сколько лет я ни пишу код, без конца убеждаюсь в двух вещах:
1. Если стоит выбор между мутабельностью и иммутабельностью — без раздумий выбирай иммутабельность.
2. Если стоит выбор между наследованием и композицией — без раздумий выбирай композицию.
Каждый раз, когда я выбираю мутабельность, я получаю хрупкую программу с непредсказуемыми сайд-эффектами.
Каждый раз, когда я выбираю наследование, я получаю запутанный код, который трудно переиспользовать (хотя обещали, что будет наоборот) и невозможно читать, не прыгая по нескольки классам с полузащищённым API.
Интересно, что и мутабельность, и наследование осложняют типизацию и привносят костыли:
@self-out, @this-out, @require-extends.Я не Егор Бугаенко и не утверждаю, что мутабельность и наследование прям вот совсем не нужны. Но если есть выбор (90% случаев на моей open source практике) — советую воздерживаться.
💯91👍42🔥11🤔7❤4🫡3
9 полезных плагинов
В блоге JetBrains вышел обзор плагинов Димы Дерепко:
• .gitattributes support
• Git Codeowners
• Cron / Crontab Support
• Sitemap Support
• TempestPHP (поддержка фреймворка автора канала PHP Annotated)
•🪲 Buggregator
• PHP Dump (показывает опкоды и AST)
• FileSystem Info (выводит информацию по папкам и файлам: кол-во файлов, размер, LOC)
• Git Churn (анализирует частоту изменений файлов в Git)
https://blog.jetbrains.com/phpstorm/2025/11/phpstorm-plugins-you-might-not-know/
P.S. Мне Дима тоже периодически предлагает сделать что-то полезное для моих проектов. И у меня уже есть идея!
В блоге JetBrains вышел обзор плагинов Димы Дерепко:
• .gitattributes support
• Git Codeowners
• Cron / Crontab Support
• Sitemap Support
• TempestPHP (поддержка фреймворка автора канала PHP Annotated)
•
• PHP Dump (показывает опкоды и AST)
• FileSystem Info (выводит информацию по папкам и файлам: кол-во файлов, размер, LOC)
• Git Churn (анализирует частоту изменений файлов в Git)
https://blog.jetbrains.com/phpstorm/2025/11/phpstorm-plugins-you-might-not-know/
P.S. Мне Дима тоже периодически предлагает сделать что-то полезное для моих проектов. И у меня уже есть идея!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍39🔥18❤9😴5
Ищу напарника на стрим по Typhoon
На следующей неделе хочу провести Typhoon-стрим. Мы наконец-то напишем простой инструмент на базе typhoon/type, который будет полезен в самых обыкновенных проектах.
Чтобы было веселее писать код, приглашаю любого из вас присоединиться в роли второго пилота. Нужно быть в теме статического анализа в PHP, оценивать свой уровень на middle+ и не бояться говорить на камеру в прямом эфире.
Желающие, скидывайте в личные сообщения канала Пых свой GitHub.
На следующей неделе хочу провести Typhoon-стрим. Мы наконец-то напишем простой инструмент на базе typhoon/type, который будет полезен в самых обыкновенных проектах.
Чтобы было веселее писать код, приглашаю любого из вас присоединиться в роли второго пилота. Нужно быть в теме статического анализа в PHP, оценивать свой уровень на middle+ и не бояться говорить на камеру в прямом эфире.
Желающие, скидывайте в личные сообщения канала Пых свой GitHub.
GitHub
GitHub - typhoon-php/type: Typhoon Type System
Typhoon Type System. Contribute to typhoon-php/type development by creating an account on GitHub.
👍14🔥13❤5😁1
Убираем null?
В конце месяца совместно с Garage Eight и Live PHP делаем митап в Санкт-Петербурге. Регистрация откроется через неделю.
В числе спикеров отчаянный борец против
Вчера мы прогоняли его доклад, а сегодня я кидаю вам пример рефакторинга своего кода...
Было
Стало
Я не считаю
В конце месяца совместно с Garage Eight и Live PHP делаем митап в Санкт-Петербурге. Регистрация откроется через неделю.
В числе спикеров отчаянный борец против
null — Владимир Романичев.Вчера мы прогоняли его доклад, а сегодня я кидаю вам пример рефакторинга своего кода...
Было
final class Context
{
/**
* @var array<non-empty-lowercase-string, Name>
*/
private array $uses = [];
public function __construct(
public readonly ?Name $namespace = null,
) {}
public function use(Name $name, ?Name $as = null): self
{
$context = clone $this;
$context->uses[($as ?? $name->last())->toLowercaseString()] = $name;
return $context;
}
}
Стало
final class Context
{
// ...
public function use(Name $name): self
{
return $this->useAs($name, $name->last());
}
public function useAs(Name $name, Name $as): self
{
$context = clone $this;
$context->uses[$as->toLowercaseString()] = $name;
return $context;
}
}
Я не считаю
null абсолютным злом, тем более, что в PHP он явный, но иногда действительно можно сделать красивее без него.👍36🥴34❤13🔥12👎5🤔5🤡4
Garage Eight × LivePHP × Пыхап в Санкт-Петербурге
В следующий четверг в 18:30 мы совместно с Garage Eight и Live PHP делаем митап в офисе "гаражей".
В программе:
💣 NULL. Выбросить нельзя использовать
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно победили зеркалированные
Виктор Михайлов расскажет, как использовать надёжные реплицируемые очереди в кролике.
🧠 Архитектура ИИ-сервиса для распознавания документов
Михаил Мироненко покажет путь от MVP до продакшена.
✌️ Офлайн-гостей ждут угощения и экскурсия по офису Garage Eight с панорамным видом на город. Плойка и кикер также к вашим услугам!
📍 Митап пройдёт 27 ноября в 18:30 в питерском офисе Garage Eight. Вход бесплатный, но нужно зарегистрироваться.
📹 Как обычно, будет трансляция на YouTube и VK Видео с записью!
В следующий четверг в 18:30 мы совместно с Garage Eight и Live PHP делаем митап в офисе "гаражей".
В программе:
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно победили зеркалированные
Виктор Михайлов расскажет, как использовать надёжные реплицируемые очереди в кролике.
Михаил Мироненко покажет путь от MVP до продакшена.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍27🔥18❤8
Только что на php.net опубликовали PHP 8.5!
Тег уже два дня как стоит, но я ждал финального аккорда.
По этому поводу держите мой доклад со Стачки «PHP 8.5 не сбавляет темп!». Из него вы узнаете про основные фичи новой версии и нюансы их применения.
Основные таймкоды:
01:04 Все способы получения первого элемента массива в PHP (в т. ч. бредовые)
05:20 Pipe operator v3
10:56 URL Api
17:20 Clone with v2
21:24 #[NoDiscard]
24:07 Closure и FCC в константных выражениях
27:57 Persistent cURL handles
29:33 Асимметричная видимость статических свойств
30:00 Рекурсивные замыкания
37:41 Типизируем array_first()
https://youtu.be/OIFbU5oypig
https://vkvideo.ru/video-228746873_456239122
http://vudaltsov.github.io/php8.5-slides
https://php.net/releases/8.5/ru.php
Тег уже два дня как стоит, но я ждал финального аккорда.
По этому поводу держите мой доклад со Стачки «PHP 8.5 не сбавляет темп!». Из него вы узнаете про основные фичи новой версии и нюансы их применения.
Основные таймкоды:
01:04 Все способы получения первого элемента массива в PHP (в т. ч. бредовые)
05:20 Pipe operator v3
10:56 URL Api
17:20 Clone with v2
21:24 #[NoDiscard]
24:07 Closure и FCC в константных выражениях
27:57 Persistent cURL handles
29:33 Асимметричная видимость статических свойств
30:00 Рекурсивные замыкания
37:41 Типизируем array_first()
https://youtu.be/OIFbU5oypig
https://vkvideo.ru/video-228746873_456239122
http://vudaltsov.github.io/php8.5-slides
https://php.net/releases/8.5/ru.php
YouTube
PHP 8.5 не сбавляет темп! / Валентин Удальцов / Стачка, 3 октября 2025
Слайды: http://vudaltsov.github.io/php8.5-slides/
После насыщенного PHP 8.4 (property hooks, aviz, lazy objects, BCMath\Number) казалось, что должен случиться перерыв...
Но не тут-то было:
- pipe operator,
- clone with,
- aviz для статических свойств,
…
После насыщенного PHP 8.4 (property hooks, aviz, lazy objects, BCMath\Number) казалось, что должен случиться перерыв...
Но не тут-то было:
- pipe operator,
- clone with,
- aviz для статических свойств,
…
4🔥70👍25❤3
Когда проекты растут, а требований становится больше, скорость разработки начинает упираться не в язык или фреймворки, а в процессы, инструменты и организацию работы.
С 1 по 5 декабря сезон Podlodka PHP Crew о том, как разгонять PHP-разработку без стресса и перегрузов.
Все темы прикладные, с упором на ускорение команд и уменьшение рутины:
📄 Контракты пишем — код генерим — Александр Забанов (Вебпрактик): contract-first подход, который снижает количество ошибок и делает интеграции предсказуемыми.
⚙️ Background-агенты в разработке — Пётр Мязин («Пятиминутка PHP») покажет, как построить процесс вокруг ИИ-инструментов.
🧩 Тесты для ускорения — Александр Макаров (Twindo): о роли тестирования в скорости разработки и как распределить ответственность между разработчиками, QA и LLM.
🚦 Светофоры для разработчиков — Ярослав Тарасов (Skyeng) расскажет, как ускорить обратную связь от коммита до продакшена.
🔥 Баланс фич и техдолга — Дмитрий Кириллов поделится холиварным кейсом «100% фичи, 0% техдолг».
🤖 От промпта к продакшену — Павел Бучнев (Spiral Scout,🔥 ) объяснит, почему пора мыслить контекстами, а не только промптами.
Программа и билеты: https://podlodka.io/phpcrew
По промокоду phpyh7 скидка 500р!
С 1 по 5 декабря сезон Podlodka PHP Crew о том, как разгонять PHP-разработку без стресса и перегрузов.
Все темы прикладные, с упором на ускорение команд и уменьшение рутины:
📄 Контракты пишем — код генерим — Александр Забанов (Вебпрактик): contract-first подход, который снижает количество ошибок и делает интеграции предсказуемыми.
⚙️ Background-агенты в разработке — Пётр Мязин («Пятиминутка PHP») покажет, как построить процесс вокруг ИИ-инструментов.
🧩 Тесты для ускорения — Александр Макаров (Twindo): о роли тестирования в скорости разработки и как распределить ответственность между разработчиками, QA и LLM.
🚦 Светофоры для разработчиков — Ярослав Тарасов (Skyeng) расскажет, как ускорить обратную связь от коммита до продакшена.
🔥 Баланс фич и техдолга — Дмитрий Кириллов поделится холиварным кейсом «100% фичи, 0% техдолг».
🤖 От промпта к продакшену — Павел Бучнев (Spiral Scout,
Программа и билеты: https://podlodka.io/phpcrew
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17❤6👍5👌1
Напоминаю, что завтра в 18:30 мы встречаемся на совместном митапе Garage Eight × LivePHP × Пыхап!
🏢 Ждём офлайн в Санкт-Петербурге в офисе Garage Eight по адресу Новгородская, 17, Бизнес-центр М22. Вход с Кирочной улицы, мы будем вас встречать внутри. Паспорт не нужен, только регистрация. Передать место другу можно через @airkatie.
🖥 Ждём онлайн в YouTube и VK Видео. Кстати, в онлайне тоже можно будет выиграть приз за лучший вопрос!
🙅🏻♀️ Если передумал(-а) или по какой-либо причине не сможешь прийти, пожалуйста, сообщи об этом @airkatie.
До встречи на митапе!
🏢 Ждём офлайн в Санкт-Петербурге в офисе Garage Eight по адресу Новгородская, 17, Бизнес-центр М22. Вход с Кирочной улицы, мы будем вас встречать внутри. Паспорт не нужен, только регистрация. Передать место другу можно через @airkatie.
🙅🏻♀️ Если передумал(-а) или по какой-либо причине не сможешь прийти, пожалуйста, сообщи об этом @airkatie.
До встречи на митапе!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍13🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
👍24🔥13❤11
Garage Eight × LivePHP × Пыхап в Санкт-Петербурге
Мы в эфире!
💣 NULL. Выбросить нельзя использовать
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно победили зеркалированные
Виктор Михайлов расскажет, как использовать надёжные реплицируемые очереди в кролике.
🧠 Архитектура ИИ-сервиса для распознавания документов
Михаил Мироненко покажет путь от MVP до продакшена.
Залетай в YouTube и VK Видео!
Мы в эфире!
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно победили зеркалированные
Виктор Михайлов расскажет, как использовать надёжные реплицируемые очереди в кролике.
Михаил Мироненко покажет путь от MVP до продакшена.
Залетай в YouTube и VK Видео!
Please open Telegram to view this post
VIEW IN TELEGRAM
YouTube
Garage Eight × LivePHP × Пыхап в Санкт-Петербурге / 27 ноября 2025
В следующий четверг в 18:30 мы совместно с Garage Eight и Live PHP делаем митап в офисе "гаражей".
В программе:
💣 NULL. Выбросить нельзя использовать
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно…
В программе:
💣 NULL. Выбросить нельзя использовать
После этого доклада от Владимира Романичева разрешается бить морды.
🧬 RabbitMQ: как кворумные очереди окончательно…
2🔥19👍9❤1
-export-ignore в .gitattributes
Оказывается, в
Особенно удобно для
📁 Параграф в документации gitattributes
📁 PR в Composer, который добавил поддержку -export-ignore аж в 2021
Исправлено 10 декабря: добавил правило
Оказывается, в
.gitattributes можно описывать правила от обратного, то есть сначала применять ко всему, а потом точечно отменять при помощи знака -.Особенно удобно для
export-ignore: сначала игнорим всё, а потом возвращаем только важные для распространения пакета файлы:
* export-ignore
/src/ -export-ignore
/src/** -export-ignore
/composer.json -export-ignore
/README.md -export-ignore
/CHANGELOG.md -export-ignore
/LICENSE -export-ignore
Исправлено 10 декабря: добавил правило
/src/** -export-ignore, см. пост.Please open Telegram to view this post
VIEW IN TELEGRAM
1👍36❤6🔥5
Пых
-export-ignore в .gitattributes Оказывается, в .gitattributes можно описывать правила от обратного, то есть сначала применять ко всему, а потом точечно отменять при помощи знака -. Особенно удобно для export-ignore: сначала игнорим всё, а потом возвращаем…
Саша Макаров попросил поздравлять его контрибьютами в Yii, поэтому я, вооружившись новым знанием, отправил PR в yiisoft/package-template.
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
samdark blog ☕️ (Alexander Makarov)
🎉 Accepting birthday gifts
Tomorrow is my birthday. I'd gladly accept pull request to Yii repositories as a gift. Thanks!
Tomorrow is my birthday. I'd gladly accept pull request to Yii repositories as a gift. Thanks!
🎉75❤18👍14🍾9🤮4👎2
Пых
-export-ignore в .gitattributes Оказывается, в .gitattributes можно описывать правила от обратного, то есть сначала применять ко всему, а потом точечно отменять при помощи знака -. Особенно удобно для export-ignore: сначала игнорим всё, а потом возвращаем…
Выяснилось, что
В документации к gitattributes это есть (RTFM):
Итоговый рабочий вариант (проверено при помощи
Закинул исправляющий PR в yii-soft/package-template.
/src/ -export-ignore разыгноривает только саму директорию src. Для файлов надо ещё добавить правило /src/** -export-ignore.В документации к gitattributes это есть (RTFM):
The rules by which the pattern matches paths are the same as in .gitignore files, with a few exceptions:
- negative patterns are forbidden
- patterns that match a directory do not recursively match paths inside that directory (so using the trailing-slashpath/syntax is pointless in an attributes file; usepath/**instead)
Итоговый рабочий вариант (проверено при помощи
git archive с директориями и файлами разной вложенности):
* export-ignore
/src/ -export-ignore
+/src/** -export-ignore
/composer.json -export-ignore
/README.md -export-ignore
/CHANGELOG.md -export-ignore
/LICENSE -export-ignore
Закинул исправляющий PR в yii-soft/package-template.
👍19❤8🔥1
