uk
Feedback
Пых

Пых

Відкрити в Telegram

Блог Валентина Удальцова о разработке на PHP. Хобот @phpyhobot https://youtube.com/@phpyh https://vkvideo.ru/@phpyh https://t.me/isPHPdying Статистика: https://t.me/INOTAROBOT?start=st1219340804 Для связи используйте личные сообщения канала.

Показати більше
8 065
Підписники
-124 години
-57 днів
-6330 день

Триває завантаження даних...

Залучення підписників
липень '26
липень '26
+60
в 0 каналах
червень '26
+106
в 0 каналах
Get PRO
травень '26
+141
в 0 каналах
Get PRO
квітень '26
+66
в 0 каналах
Get PRO
березень '26
+72
в 1 каналах
Get PRO
лютий '26
+92
в 3 каналах
Get PRO
січень '26
+83
в 2 каналах
Get PRO
грудень '25
+69
в 3 каналах
Get PRO
листопад '25
+89
в 0 каналах
Get PRO
жовтень '25
+90
в 1 каналах
Get PRO
вересень '25
+131
в 3 каналах
Get PRO
серпень '25
+162
в 4 каналах
Get PRO
липень '25
+161
в 3 каналах
Get PRO
червень '25
+144
в 17 каналах
Get PRO
травень '25
+143
в 2 каналах
Get PRO
квітень '25
+138
в 3 каналах
Get PRO
березень '25
+125
в 3 каналах
Get PRO
лютий '25
+238
в 5 каналах
Get PRO
січень '25
+177
в 6 каналах
Get PRO
грудень '24
+235
в 1 каналах
Get PRO
листопад '24
+383
в 5 каналах
Get PRO
жовтень '24
+269
в 4 каналах
Get PRO
вересень '24
+103
в 1 каналах
Get PRO
серпень '24
+132
в 2 каналах
Get PRO
липень '24
+89
в 0 каналах
Get PRO
червень '24
+106
в 4 каналах
Get PRO
травень '24
+177
в 2 каналах
Get PRO
квітень '24
+266
в 0 каналах
Get PRO
березень '24
+365
в 1 каналах
Get PRO
лютий '24
+658
в 0 каналах
Get PRO
січень '24
+352
в 5 каналах
Get PRO
грудень '23
+274
в 3 каналах
Get PRO
листопад '23
+140
в 3 каналах
Get PRO
жовтень '23
+121
в 1 каналах
Get PRO
вересень '23
+191
в 0 каналах
Get PRO
серпень '23
+354
в 0 каналах
Get PRO
липень '23
+328
в 0 каналах
Get PRO
червень '23
+354
в 0 каналах
Get PRO
травень '23
+493
в 0 каналах
Get PRO
квітень '23
+290
в 0 каналах
Get PRO
березень '23
+689
в 0 каналах
Get PRO
лютий '23
+353
в 0 каналах
Get PRO
січень '23
+250
в 0 каналах
Get PRO
грудень '22
+217
в 0 каналах
Get PRO
листопад '22
+146
в 0 каналах
Get PRO
жовтень '22
+113
в 0 каналах
Get PRO
вересень '22
+74
в 0 каналах
Get PRO
серпень '22
+166
в 0 каналах
Get PRO
липень '22
+143
в 0 каналах
Get PRO
червень '22
+142
в 0 каналах
Get PRO
травень '22
+67
в 0 каналах
Get PRO
квітень '22
+54
в 0 каналах
Get PRO
березень '22
+57
в 0 каналах
Get PRO
лютий '22
+141
в 0 каналах
Get PRO
січень '22
+157
в 0 каналах
Get PRO
грудень '21
+181
в 0 каналах
Get PRO
листопад '21
+92
в 0 каналах
Get PRO
жовтень '21
+64
в 0 каналах
Get PRO
вересень '21
+47
в 0 каналах
Get PRO
серпень '21
+63
в 0 каналах
Get PRO
липень '21
+75
в 0 каналах
Get PRO
червень '21
+127
в 0 каналах
Get PRO
травень '21
+62
в 0 каналах
Get PRO
квітень '21
+113
в 0 каналах
Get PRO
березень '21
+238
в 0 каналах
Get PRO
лютий '21
+316
в 0 каналах
Get PRO
січень '21
+242
в 0 каналах
Get PRO
грудень '20
+3 333
в 0 каналах
Дата
Залучення підписників
Згадування
Канали
22 липня+6
21 липня+3
20 липня+4
19 липня+2
18 липня+2
17 липня+2
16 липня+4
15 липня+5
14 липня+1
13 липня+1
12 липня0
11 липня+7
10 липня+2
09 липня+3
08 липня+2
07 липня+3
06 липня+2
05 липня0
04 липня+5
03 липня+3
02 липня+1
01 липня+2
Дописи каналу
Repost from Пых.конф
Программа Пыхника’26 У нас сразу три отличные новости! 🔥 Мы расширили программу: вместо запланированных восьми секций на Пых
+1
Программа Пыхника’26 У нас сразу три отличные новости! 🔥 Мы расширили программу: вместо запланированных восьми секций на Пыхнике’26 будет одиннадцать. Все доклады из шорт-листа оказались слишком крутыми, и мы решили никого не вычёркивать. Цена билета та же. 🥳 Онлайн-доклады пройдут в прямом эфире с 7 по 9 сентября. Пыхник’26 теперь не однодневное мероприятие, а целая PHP-неделя, которая завершится большой офлайн-встречей 11 сентября в Art Village. 🤩 Первый онлайн-доклад Дмитрия Dantes будет открытым! Посмотреть его смогут все желающие. 7 сентября 📹 • Компилируемый PHP: перспективы и возможности — Дмитрий Dantes 8 сентября 📹 • AI-first архитектура PHP-приложений — Дмитрий Кириллов • Возвращаем gRPC в PHP — Вадим Занфир 9 сентября 📹 • Testo: тестирование со вкусом хинкали — Алексей Гагарин 11 сентября 🏠 • Request-Reply без ожидания и блокировок — Валентин Удальцов • От скучной генерации к инженерии с ИИ — Данил Щуцкий • Ломаем PHP-системы, чтобы они не падали — Маргарита Моногарова • PHP в бинарнике на примере YiiPress — Александр Макаров • Архитектура интеграций в PHP: как пережить чужие API — Олег Мифле • AI-трансформация в PHP-команде: куда переехал bottleneck — Денис Кукуреко • Флипчарт-сессия «Архитектурный экстремизм» Программа готова — дальше дело за вами: https://planeta.ru/campaigns/pyhnik26 Билет теперь можно оплатить от компании — присылайте на conf@phpyh.ru тип, количество, реквизиты.

2
Одной проблемой в Rector меньше Подписчик Илья Манютин зарешал тикет, который я на прошлой неделе открыл в Rector. Спасибо огромное за потраченное время и токены! После релиза с удовольствием уберу ClassPropertyAssignToConstructorPromotionRector из skip.
2 605
3
У меня самые умные подписчики в IT 💙 — нашли ошибку за секунды. Ну а для меня этот комментарий стал поводом разложить всё по полочкам. DI — Dependency Injection Подход, при котором код явно декларирует необходимые зависимости и получает их снаружи, а не создаёт, не хардкодит и не извлекает их сам. function logToFile(string $message): void { // не DI file_put_contents(__DIR__ . '/../app.log', $message, FILE_APPEND); } final class StreamLogger extends Psr\Log\AbstractLogger { public function __construct( // DI private string $stream, ) {} // ... } Как видите, зависимостью может быть что угодно, не только интерфейс: строка, число, инстанс финального класса. Здесь часто проводят параллель с принципом Голливуда («Don’t call us, we’ll call you»): не ищите зависимости, мы их для вас соберём и передадим. Мне ещё нравится на пальцах объяснять так: Привет, я A, моя компетенция — α. Чтобы выполнить α, мне потребуются: x, опционально y и кто-то, кто умеет β. Предоставите — всё сделаю. Нет — сорян. Зависимости можно передавать через конструктор, параметр метода, путём клонирования with-методом (поддерживается в Symfony и Thesis DIC) или через сеттер (не рекомендую, так как мутабельно и можно получить неполный стейт или проблемы похуже в асинхронном сетапе). DIC — Dependency Injection Container Сугубо опциональная вещь! Контейнер призван облегчить сборку графа зависимостей в крупном проекте, но никто не мешает собирать приложение руками: // код в стиле DI, но контейнера нет $app = new App( logger: new StreamLogger(__DIR__ . '/../app.log'), ); Большинство современных библиотек написано в стиле DI, но не требует контейнера. В README как раз обычно и показывают, как всё собрать "на коленке". DIP — Dependency Inversion Principle Последний принцип из SOLID. Он призван снизить каплинг и повысить переиспользуемость кода за счёт опоры на абстракции. Обратите внимание, что в оригинальной формулировке принципа не используется понятие «интерфейс»: A. High level modules should not depend upon low level modules. Both should depend upon abstractions. B. Abstractions should not depend upon details. Details should depend upon abstractions. Robert C. Martin, «The Dependency Inversion Principle», C++ Report, 1996 В C++, о котором идёт речь в статье, не было отдельной языковой конструкции interface: Мартин выражал объектные интерфейсы чисто абстрактными классами. Но в той же статье он отдельно приводит stdio.h как пример Dependency Inversion без всяких классов и виртуальных методов. В наш StreamLogger тоже можно передать не только путь к локальному файлу: $stdOutLogger = new StreamLogger('php://stdout'); $compressedLogger = new StreamLogger('compress.zlib:///var/log/app.log.gz'); $remoteLogger = new StreamLogger('ftp://logger:secret@logs.example.com/app.log'); Внезапно для работы с разными потоками нам не потребовался interface! Строковый URI выбирает конкретную реализацию, а StreamLogger работает через общую абстракцию PHP-стримов. Инверсия зависимостей здесь реализована не в нашем коде, а в PHP: контракт — PHP Streams API, конкретные врапперы — file, php, compress.zlib, ftp и пользовательские протоколы. StreamLogger пользуется этим контрактом, не зная, какая реализация скрывается за URI. Получается, «абстракция» не тождественна интерфейсу или абстрактному классу. Даже финальный класс может абстрагировать вызывающий код от деталей реализации, пока сохраняет публичный контракт. И вот тут-то мы и нащупали причину, по которой интерфейс может быть избыточным: Если тип сам выражает требуемую клиенту стабильную абстракцию и не протекает низкоуровневыми деталями — на него можно опереться напрямую. ⸻ 🌿 Анонсировали доклады Данилы Щуцкого и Саши Макарова на Пыхнике!
2 462
4
Найдите ошибку в терминологии.
Найдите ошибку в терминологии.
2 916
5
Ура! Если кто-то хочет пофиксить, вот вам готовая несложная задачка.
Ура! Если кто-то хочет пофиксить, вот вам готовая несложная задачка.
5 064
6
Rector, это не то же самое!!! Пошёл делать тикет и нашёл уже существующий с ровно такой же проблемой. И знаете, что там ответ
Rector, это не то же самое!!! Пошёл делать тикет и нашёл уже существующий с ровно такой же проблемой. И знаете, что там ответил мейнтейнер? That's expected, if the type not match, that means a design issue in the first place, if property is private and nullable, and filled via constructor, that means the constructor should be nullable param as well as it just assign -> fill, no nullable check. Почему он неправ Есть большая разница между состоянием, в котором объект оказывается при создании, и состоянием, в которое он может прийти по ходу выполнения логики. В моём случае null означает «больше нет», а не «никогда не было». Иными словами, тип параметра описывает то, что допустимо на входе, а тип свойства — все состояния объекта за его жизнь. В первую очередь мы декларируем параметр и свойство по отдельности, и уже во вторую рассматриваем возможность склеить их в promoted, но только если типы эквивалентны. Открыл новую issue с моими пояснениями, посмотрим, дойдёт или нет... ⸻ 🌿 Выбрали первый доклад на Пыхник’26!
4 478
7
or <=> if Замешивая в 🥟 Testo Алексея Гагарина тикет про исключения, обнаружил такой фрагмент: $classOrObject->getCode() === 0 or $result->withCode($classOrObject->getCode()); Конформный пыхарь написал бы так: if ($classOrObject->getCode() !== 0) { $result->withCode($classOrObject->getCode()); } Если что, withCode() мутирующий, $result = не пропущен. Почему or, а не ||? Конкретно в этом случае разницы нет. Но вообще оператор or на самом дне списка приоритетов, даже ниже, чем присваивание. Это позволяет писать так: $x = foo() or bar(); // ($x = foo()) or bar(); $x = foo() || bar(); // $x = (foo() || bar()); Короче, как вам такой стиль кодирования?
4 240
8
Эквайринг Т-Банка. 2026 год Повторное выставление счёта (ручка Init) бросает ошибку о том, что такой заказ уже есть, вместо т
Эквайринг Т-Банка. 2026 год Повторное выставление счёта (ручка Init) бросает ошибку о том, что такой заказ уже есть, вместо того, чтобы идемпотентно вернуть ссылку на оплату (PaymentURL). Окей, допустим. План Б: оборачиваю Init в try/catch и при выпадении соответствующей ошибки о дублирующемся заказе пробую GetState и CheckOrder, которые возвращают инфу по счёта. Но ни в одном из них нет PaymentURL!!! 🤬 То есть у меня есть лишь один шанс записать PaymentURL после получения ответа от Т-Банка. А если ответ не дошёл по сети? А если сервис упал? А если БД нагружена? А если кролик отошёл погрызть морковки? Ну как так-то нахуй... Решение, конечно, есть: при ретрае и ошибке о дубле создавать новый заказ с другим ID. Но это означает, что я уже не могу без таблички скоррелировать ID своего инвойса с их ID. А это дополнительное I/O на пустом месте, брошенные заказы в админке Т-Банка и усложнённое расследование инцидентов. Если у кого-то есть друзья в Т-Банке, попросите исправить этот позор.
4 250
9
Про кодогенерируемые контейнеры.
4 058
10
Відеоповідомлення
3 807
11
Первый бенчмарк thesis/dic Смоделировал следующий жизненный сценарий работы неумирающего приложения: Задепоили приложение в р
Первый бенчмарк thesis/dic Смоделировал следующий жизненный сценарий работы неумирающего приложения: Задепоили приложение в рантайме а-ля RoadRunner, собрали контейнер и готовы принимать запросы. Ни один сервис не инстанциирован, но контейнер максимально готов. Как быстро испытуемые вернут инстанс контроллера с несколькими зависимостями? Сравнение, конечно, не совсем равнозначное, потому что только у Thesis есть этап диспоуза сервисов после скоупа и не во всех контейнерах есть полноценные scoped сервисы. Но в целом результат ожидаемый. Скомпилированный контейнер Symfony почти эквалентен написанному руками коду (manual). Thesis (current) быстрее конкурентов, потому что рефлексию и резолвинг графа зависимостей он делает на этапе сборки, а в рантайме вызывает полностью готовые фабрики. Для бенчмарка попробовал #[Bench] в 🐘 Testo.
3 864
12
Запустили краудфандинг!!! 11 сентября в Art Village под Москвой собираем небольшую PHP-конференцию на 120 участников: один по
Запустили краудфандинг!!! 11 сентября в Art Village под Москвой собираем небольшую PHP-конференцию на 120 участников: один поток, 8 докладов и много живого общения. Средства на мероприятие собираем через краудфандинг. Можно взять офлайн-билет, доступ к записям, футболку «Вы вымрете, а я останусь» или просто поддержать проект любой суммой. https://planeta.ru/campaigns/pyhnik26
4 060
13
Немає тексту...
4 961
14
Немає тексту...
4 561
15
🍆 Thesis Dic Прошло полтора года с тех пор, как я всерьёз начал пилить DI контейнер для Thesis. Набор требований у меня был большой: Модульность Всё есть модуль, включая само приложение. PHP DSL Выразительный и лаконичный, не на массивах. Типобезопасность Не строковые идентификаторы, а объекты с дженериком. Легко написать плагин статанализатора для тайпчека аргументов. Импорт/экспорт У модуля прозрачный типизированный контракт на вход (конфигурация) и на выход (экспорт сервисов). Scoped сервисы В асинхронном приложении можно писать код как в умирающем: инжектить репозиторий по интерфейсу в конструктор обработчика и не замечать, что у него под капотом транзакция, открытая специально для текущего сообщения. Disposer-коллбэки К сервису, не меняя его код, можно привязать функцию, которая будет вызвана по завершении скоупа. Удобно для закрытия ресурсов и остановки фоновых корутин. Предсказуемый автовайринг Модуль из vendor не может внезапно затереть сервис в модуле проекта. Все биндинги локализованы, нет глобального пространства имён. Автоконфигурация Возможность порефлексировать сервисы перед сборкой и по подтипу или атрибуту накинуть теги. Теги Имплементируют Tag<T> и содержат типизированные данные. Через хук можно собрать протегированные сервисы, преобразовать их и заинжектить куда угодно. First-class callable сервисы myFunc(...) и $service->method(...) легко объявить сервисами, частично применить аргументы, прочитать атрибуты и подключить как обработчики сообщений, не написав CompilerPass на 1000 строк. И вот мы здесь. 30 июня, я только что поставил тег 0.5.0 с осознанием, что до 1.0 рукой подать и я готов с вами поделиться! В README есть всё необходимое для первого знакоства. В docs/ несколько рецептов. https://github.com/thesis-php/dic https://github.com/thesis-php/symfony-console-module /** * @implements Module<Ref<Application>> */ final readonly class App implements Module { public function configure(Dic $dic): mixed { $dic->apply(new AutoconfigureCommands()); $dic->function(self::greet(...)); return $dic->import(new SymfonyConsoleModule(name: 'Пых')); } #[AsCommand('greet', aliases: ['g'])] private static function greet(#[Argument] string $name, SymfonyStyle $io): int { $io->title("Hello, {$name}!"); return Command::SUCCESS; } } exit(Dic::run( module: new App(), main: static fn(Application $app) => $app->run(), ));
4 885
16
Скидывайте идеи футболок под этим сообщением.👇
4 833
17
Скидывайте идеи футболок под этим сообщением.👇
1
18
Відеоповідомлення
4 971
19
Какой стиль оформления значений в исключениях лучше читается?
5 929
20
Как тебе идея?
6 788