ru
Feedback
PHP Fart Time

PHP Fart Time

Открыть в Telegram

Привет, фартаны! Дурачимся, пилим OpenSource и рассказываем про передовые технологии в php. Авторы контента: @roxblnfk и @butschster

Больше
356
Подписчики
+524 часа
+347 дней
+18030 день
Архив постов
#МыслиВслух Мы с Павлом как-то готовили доклад. Начали делать его примерно за 2 часа до выступления. Наверное поэтому получил
#МыслиВслух Мы с Павлом как-то готовили доклад. Начали делать его примерно за 2 часа до выступления. Наверное поэтому получилось так всрато, но сносно. Там я говорил о том, что экосистема Spiral акцентируется на объединении разных миров разработки, а скорость - просто приятный бонус: gRPC имплементируется на любом популярном языке, у Temporal есть SDK на разных языках, кроме того, RoadRunner хорошо объединяет go и PHP. Так вот. Сегодня я обратил внимание на такую вещь, что объединение миров работает и в другую сторону — не на расширение стека, а на сужение. Вы когда-нибудь решали задачу утилизации компетенций? Нафига нам питонист, если задачу можно сделать в одном PHP стеке? Но питонист уже есть и мы не можем его заменить. Нужно его эффективно утилизировать. Берём Temporal и пусть питонист питонирует. Его труды идеально встроятся в наши Workflow!

#Article Привет, привет всем любителям PHP! 🎉 Хочу поделиться свежей статьей под названием "Как раскрыть сверхспособности высокопроизводительных очередей для PHP-приложений и не сойти с ума!" 🚀 Знаете, я изучал тему очередей на PHP и обнаружил пару проблемок. Вроде бы все классно, но, честно говоря, PHP не слишком подходит для крутых инфраструктурных штуковин. Такой интерпретируемый характер и блокирующая модель IO могут сильно торомозить их работу Короче это тупо неэффективно. 🤔 И вот однажды один человек подумал, а почему бы не использовать в этом деле Golang? 🔥 Go умеет делать кучу дел одновременно (горутины), управляет ресурсами как настоящий профи, работает быстро как молния и еще и сокетами управляет на уровне близком к железу. Просто магия! Итак, в моей статье я рассказываю о супер-мега-крутых очередях на RoadRunner (о плагине "Jobs"). 💪 Там PHP и Go нашли свою любовь и объединились в команду. Теперь PHP-разработчики могут наслаждаться всеми плюшками обоих языков и создавать высокопроизводительниые шедевры! Но это еще не все, фартаны! Также, я раскрываю стратегии использования очередей. Мы будем погружаться в мир загадочных штуковин, как "Фанатик с запоздалыми задачами", "Король бесконечных повторений" и "Независимый ковбой с ретрайами". Это как сказка, только в мире программирования! Так что, прямо сейчас отправляйтесь по ссылочке https://butschster.medium.com/unleashing-the-power-of-high-performance-queue-services-for-php-applications-dcc5c1426511! 😄 #PHP + #Go = Unstoppable! 💪 Жду ваших комментариев и обсуждений! 🙌 P.s. Мы как-то побенчили джобы разных реализаций. Оказалось, что очереди в отделении почты разгребаются быстрее, чем в Laravel.

#Article #Типизация #php #️⃣ Variadic параметр Вроде тут и сказать нечего. Ну поставил три точки в параметре и всё. Ан нет. Приколов хватает. Погнали  ⭕️ Что известно Variadic параметр, он же "списки аргументов переменной длины", пользователем с помощью добавления (сюрприз!) многоточия. Примерно столько вы можете прочитать про variadic в документации. А ещё про то, что в него можно распаковывать итерируемые значения другим многоточием.
function toArray(...$items): array { return $items; }
$a = ['foo', 'bar'];
toArray(...$a);
Variadic является опциональным параметром. Всегда. Т.е. вы можете ничего в него не передавать и ему с того норм. > Кстати, многие путают понятия "аргумент" и "параметр". Параметр - то, что в определении функции, аргумент - значение, которое передаётся в функцию. Зачем он нужен, если и так можно передать сколько угодно аргументов, а потом вынуть их с помощью func_get_arg(), как делали ещё наши предки? Кроме того, мы можем в конце списка параметров сунуть массив и даже распаковка не понадобится при вызове функции. function foo(Foo $a, array $myVariadic = []) {}. А затем, что в variadic умеет в типизацию! (про типы см. предыдущий пост).
function foo(Foo $a, Bar ...$variadic) {}
Теперь только объекты Bar попадут в массив $variadic. Ну это и так все знали. ⭕️ Приколы с распаковкой Распаковывая iterable в variadic, ключи могут быть разные. Если вы распаковываете список (ключи типа int), то их порядок будет сброшен. Т.е. распаковка массива [3 => 'a', 2 => 'b', 1 => 'c'] приведёт к ['a', 'b', 'c'] в вариадике. Ассоциативный массив останется ассоциативным массивом с теми же ключами. Но не всегда можно смешивать целочисленные ключи со строковыми. При распаковке аргументов из массива, как и при передаче именованных+позиционных аргументов, позиционные аргументы должны идти перед именованными. Причём сортируется это по параметрам 💥 ⭕️ Именованные аргументы (PHP 8.0) Поиграем в игру. Есть сигнатура bar(int $a = 1, int $b = 2, int ...$c). Что попадёт в $c? (если нажать на один скрытый элемент — откроются все) bar(a: 1, c: 3) - `["c" => 3]` bar(c: [1, 2, 3]) - `Fatal Error` bar(foo: 3) - `["foo" => 3]` bar(1, 2, a: 3) - `Fatal Error` bar(c: 3, a: 1, b: 2) - `["c" => 3]` bar(foo-bar: 3) - `Syntax Error` bar(1, 2, 3, 4, foo: 5) - `[3, 4, "foo" => 5]` bar(b: 2, 3, 4, foo: 5) - `Fatal Error` Сколько промахов? Как итог: распаковка аргументов из массива даёт возможность передать любой сроковой ключ, именованные аргументы — нет. ⭕️ Хрень какая-то. Где оно надо то вообще? - Когда нужна типизация на списке аргументов, при этом не нужно сохранять ключи. При этом сигнатура точно не будет дополняться. Например, в yiisoft/injector в конструктор можно было бы передавать переменное число ContainerInterface, а не один и только один (@samdark, я смотрю на тебя). Или вот пример, как заставить передать минимум один аргумент нужного типа: function setEncoders(Encoder $encoder, Encoder ...$encoders) {}. - В атрибутах, которые конфижат непонятно что. В атрибуте Column компонента cycle/orm можно передать любые именованные аргументы сверх тех, что предопределены заранее (спасибо, variadic). Например, определяем #[Column(type: 'bigint', unsigned: true). Здесь unsigned попадёт в variadic и, если у вас MySQL, столбец будет unsigned. ⭕️ Аннотации Артефакты прошлого ещё долго будут встречаться в коде даже современном. Да, это про аннотации. Там variadic'и не поддерживаются. До недавнего времени они вообще фейлили парсер doctrine/annotations, однако там решили ограничиться просто фиксом "чтоб не падало". Поэтому (и не только) не пользуйтесь аннотациями, если есть возможность пользоваться атрибутами. ⭕️ Поддержка IDE Её нет. Пока нет известного мне способа рассказать IDE или Psalm'у, какие ключи можно передать в variadic. Можно описать тип только одного (каждого) передаваемого элемента. Если вам известно об этом больше - го в комменты.

В последнее время люди из моего окружения начали активно пользоваться Obsidian для ведения заметок и агрегирования информации. После восторженных отзывов уже и я не мог пройти мимо. Не может же быть всё так замечательно. Оказывается, может! Отличный markdown-редактор, теги, ссылки как в wiki, удобный и быстрый интерфейс с тёмной темой, даже плагины есть. Markdown рендерится красиво - блоки кода подсвечиваются, mermaid поддерживается, горячие клавиши работают, всё максимально юзабельно. Если настроить синхронизацию с облаком, то данные в меньшей степени похерятся, случись чего, ну а markdown-файлы прочитать можно будет и блокнотом. Если заюзать нормальное облако, которое умеет синкать файлы на телефоне (не яндекс.диск), то вести/просматривать заметки можно будет даже с лопаты. Собираю всё своё разбросанное по разным хранилищам в одно место, сохраняю интересные статьи со ссылками на источник и нужными тегами. Пока сеть заметок маленькая. Посмотрим, что будет через месяц-другой. Обсудить Obsidian-flow го в комменты.

Уважаймые подписчики! Вы верно чли первое правило клуба - не рассказывать о клубе. Но теперь ничего не поменялось и мы встали перед выбором. Готов ли наш канал выйти в массы?
Anonymous voting

Крошка Джун к Мидлу пришёл, и сказала кроха — что такое "хорошо", а что такое "плохо"? Предлагаю нагенерить идеи Хорошо/Плохо для повышения квалификации PHP-комьюнити

#МыслиВслух https://t.me/samdark_blog/103 Примерный перевод последнего абзаца: Чтобы избежать проблем с производительностью,
#МыслиВслух https://t.me/samdark_blog/103 Примерный перевод последнего абзаца: Чтобы избежать проблем с производительностью, вызванных тяжелой инициализацией, крайне важно откладывать инициализацию как можно дольше. Поступая таким образом, вы можете быть уверены, что приложение будет работать гладко, независимо от сложности дерева зависимостей. В умирающей модели инициализировать всё приходится заново. Однако, если ваше приложение не умирает, то инициализацию можно считать бесплатной, а в некоторых случаях отложенная инициализация может быть даже вредной. Это я к чему. Нет универсального рецепта. Всё зависит. От приложения, от того как оно работает, от сервисов, которые нужно инициализировать, и которые не нужно. Крутой доклад от @alexndrnovikov Наш всратый доклад

https://samwho.dev/load-balancing/ Наглядно и очень интересно. В связи с тем, что таких нагрузок вы всё-равно не достигните,
https://samwho.dev/load-balancing/ Наглядно и очень интересно. В связи с тем, что таких нагрузок вы всё-равно не достигните, в конце статьи всё-же можно поиграться на симуляторе.

#ВредныеСоветы ⚠ Не используйте FINAL! Есть хорошие программисты, которые топят за FINAL, а есть успешные люди.
#ВредныеСоветы ⚠ Не используйте FINAL! Есть хорошие программисты, которые топят за FINAL, а есть успешные люди.

photo content

#Article #Типизация #php #️⃣ Типизация PHP Наверное буду кэпом, если скажу, что следование строгим типам и избежание неявных преобразований уменьшает магичность кода, что ведёт к стабильности и надёжности. Поэтому в коде Spiral, Cycle и других наших продуктов мы используем строгую типизацию, где это возможно. Вроде тема понятная, но... это же PHP. А значит без нюансов не обойтись 💩 ⭕️ declare(strict_types=1); Прям из доки: по умолчанию, PHP будет преобразовывать значения неправильного типа в ожидаемые. ... Можно включить режим строгой типизации на уровне файла. В этом режиме, тип значения должен строго соответствовать объявленному, иначе будет выброшено исключение TypeError. Единственным исключением из этого правила является передача значения типа int туда, где ожидается float. ⚠️ На вызовы из внутренних функций, действие strict_types не распространяется. Обратите внимание на предупреждение. Многие core-функции не следуют строгости типов. Например, array_map() и array_filter() сделают неявное приведение типов.
print_r(array_map(fn(int $a, int $b) => $a + $b, [1, '10', 3], [4, 5, '1e2']));
---
Array (
    [0] => 5
    [1] => 15
    [2] => 103
)
А вот call_user_func() будет ругаться на несоответствие типов. Рефлексия тоже не следует строгости. Поэтому вместо newInstanceArgs/newInstance в фабрике контейнера у нас $instance = new $class(...$arguments);. Оно, может, чуть медленнее, но зато надёжнее. Теперь к костылям. ⭕️ Типизация переменных С помощью несложного текучего костыля можно привязать тип к переменной.
function makeInt(int &$i): void
{
    static $list = [];
    $list[] = $obj = new class() {
        public int $i;
    };
    $obj->i = &$i;
}

$int = 1;
makeInt($int);

$int = 42; // 42
$int = 'foo'; // Fatal error: Uncaught TypeError: Cannot assign string...
Не делайте так. ⭕️ PHP 8.2 Типы null, false и true теперь можно использовать автономно. Зачем это надо? Для вариантности. Например, при расширении метода возвращаемое значение с bool можно сузить до true или false, а nullable (?Foo) — до null. Таких кейсов в библиотеках не мало. Завезли DNF (Disjunctive Normal Form). Вот такого мутанта теперь можно будет встретить в коде: (Countable&Traversable)|array ℹ️ Что интересно, nullable-сахар (?Foo) был добавлен в PHP 7.1 ещё до Union Types. ℹ️ Всегда явно указывайте тип nullable параметров (?Foo $foo = null) а не полагайтесь только на значение null по умолчанию (Foo $foo = null). ℹ️ Тип never был добавлен в PHP 8.1. Но он вряд ли вам пригодится, если вы гоняете на RoadRunner. ℹ️ Тип callable существует только в сигнатурах функций и методов. Его нельзя указать для свойств, а значит и в Promoted properties не засунуть. А всё потому, что в разных контекстах callable может быть разным. Как же принять callable и записать в свойство? Например так:
// A class declaration
private \Closure $callback;

public function __construct(callable $callback)
{
    $this->callback = $callback(...);
}
Может у вас есть какие-то мысли, нюансы или лайфхаки вокруг типов PHP? Поделитесь в комментариях

#Hint А я напомню, что атрибуты можно использовать и в PHP 7.4 с помощью пакета spiral/attributes:^2.7 https://t.me/isPHPdying/143

Пилим очереди в Spiral Framework с различными сериализаторами. - JSON - Native serializer - Symfony Serializer - Laravel Serializable Closure - protobuf - valinor https://youtu.be/f2YvmYFkAyo

Хотел, было, добавить детализации в тексте поста, но при работе с цифрами бенчей возникли вопросы. Как этот инструмент считае
Хотел, было, добавить детализации в тексте поста, но при работе с цифрами бенчей возникли вопросы. Как этот инструмент считает avg? Оказывается, при расчёте среднего значения исключаются 10% максимальных и 10% минимальных значений. Not bad.

Бенчим protobuf и json. Видео уже грузится.
Бенчим protobuf и json. Видео уже грузится.

Рассматриваем Storybook в контексте обновления фронтовой части нового Buggregator. Поверхностное рассмотрение демонстрационного проекта Ticket Booking, в котором интегрировано всё сразу: #Spiral, #Zipkin, #Birddog, #OpenTelemetry, #Grafana, #RoadRunner, #Centrifugo и #Temporalio. https://youtu.be/Zk9E3ZBDtb8 Вуху, у нас есть чат! Теперь наши высеры можно комментировать! :)

Новый видосик. Смотрим новую бенч-либу TheDragonCode/benchmark и бенчим функции поиска по массиву по dotted path в #Yii #Laravel и #Spiral https://youtu.be/bQqbyjuaQ_I

В целом про типизацию в Laгavel
В целом про типизацию в Laгavel