PHP Fart Time
1.93K subscribers
124 photos
7 videos
2 files
221 links
Привет, фартаны!

Дурачимся, пилим OpenSource и рассказываем про пердовые технологии в php.

Авторы контента: @roxblnfk и @butschster
Download Telegram
Очередной упоротый обзор всякой фигни вокруг PHP с жиром и шутками 🚽
https://telegra.ph/V-mire-PHP-2-06-05

Зеркало на Notion, если телеграф опять все ссылки поломает.

⬆️ предыдущая часть

#Article #PHP #МыслиВслух

ℹ️ Если в конце статьи нет ссылки на следующую часть, то статья в телеге подгрузилась не полностью. В этом случае можно открыть в браузере.
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥5295💩2
#Article #Типизация

Я уже ранее публиковал заметку про любопытное отличие Promoted Properties от обычных свойств в кишках #PHP.

Promoted Properties от того и Promoted, что очень неплохо продвигались в плане маркетинга.


Например, вот такая портянка:
class CustomerDTO
{
public string $name;

public string $email;

public DateTimeImmutable $birth_date;

public function __construct(
string $name,
string $email,
DateTimeImmutable $birth_date
) {
$this->name = $name;
$this->email = $email;
$this->birth_date = $birth_date;
}
}


превращается в такую:

class CustomerDTO
{
public function __construct(
public string $name,
public string $email,
public DateTimeImmutable $birth_date,
) {}
}


Вау! Круто!
Но не раскрыта тема комментариев.
Если вы не пишете комментарии в коде, то вам, в прочем, без разницы 😑 но мне вот приходится 😫

Как правило, если требуется указать более точный "псалмовый" тип, то он перемещается из аннотации @var в аннотацию @param над конструктором, поэтому иногда получается такое говно, в котором нужный тебе параметр пойти найди.
А т.к. я обычно пишу непонятные тулзы, которые хер пойми как работают, то в комментариях часто нужен не только текст, но и вставки кода, дополнительные аннотации типа @internal, @note, @since, @see, @link.

И хорошего решения тут нет.

👉 Писать портянку под @property — тем всратее, чем больше комментариев и параметров.

👉 Писать типы и комментарии непосредственно над параметром — всрато.

class CustomerDTO
{
public function __construct(
/**
* @var non-empty-string Comment here
* Example here
*/
public readonly string $name,
//...
) {}
}


👉 Не использовать Promoted Properties и дублировать комментарий — всрато, но есть исключения (если свойство публичное, а конструктор internal, то в конструкторе можно обойтись только типом).
И даже если сделаешь красиво, то всё-равно потом придёт какой-нибудь умник с ректором или CS фиксером и запромоутит разом все параметры 🚽
Please open Telegram to view this post
VIEW IN TELEGRAM
#Article

Кстати, а вставки кода в комментариях — тоже кучерявая тема в #PHP.

👉 Есть Java-like вариант: оборачивать тегами <code>. Скуфы, мб, помнят.
Но мы, вроде, уже ушли от HTML среди PHP 😏
class CustomerDTO
{
/**
* @var non-empty-string Comment here
*
* <code>
* $x = foo()->bar();
* </code>
*/
public readonly string $name;
}


👉 Есть Python-like вариант: делать отступы
class CustomerDTO
{
/**
* @var non-empty-string Comment here
*
* $x = foo()->bar();
*/
public readonly string $name;
}

Тут не очень очевидно, сколько пробелов от звёздочки должно быть: по логике 1+4, но не сходится с разметкой Tab-ов.
Это активно используется в Symfony и PhpStorm это даже рендерит. Кстати, кто знает, как отключить этот рендеринг для классов из vendor?

👉 Есть Markdown-like вариант:
class CustomerDTO
{
/**
* @var non-empty-string Comment here
*
* ```php
* $x = foo()->bar();
* ```
*/
public readonly string $name;
}

Мне нравится markdown, но это не рендерится PhpStorm'ом. Однако, рендерится документором.
Python-like на документоре не проверял, может тоже рендерит.
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔8🔥2
Очередная #ТоксикСреда.

Как не хотелось не трогать сам PHP, но придётся, потому что моя жепь с этого немного подгорела на #RandomBeer в предыдущую пятницу.

PHP Lazy Objects #Article
137
#Article
На канале Пых сегодня Валентин с Андреем по-pipes-дят, т.е. обсудят новый Pipe оператор.
А у меня для вас тоже что-то есть на тему: заметка pipes в бизнес-процессах.

Happy Pipes Day!
15💩76
В этой статье вы узнаете, как я всрал 4 дня на проект, который мог бы запилить за 4 часа, если бы сразу выбрал другой стек.
И как прошло моё знакомство с BosonPHP и Symfony AI.

👩‍💻 roxblnfk/happy-wife-happy-life
Не забывайте про звёздочки: они помогают бесполезным проектам улетать в топ :)

#Article
Please open Telegram to view this post
VIEW IN TELEGRAM
😁30🔥16
#Article
💀 Как один ORM-запрос съел 300 МБ навсегда

История из нашего проекта: неоптимальный запрос через ORM загрузил ~100К записей из базы. Worker в RoadRunner вырос с 80 до ~500 МБ... и больше никогда не вернулся обратно.

Звучит как утечка памяти? Спойлер: это не баг, а особенность архитектуры PHP.

💡 Неочевидный факт: PHP никогда не возвращает память ОС в long-running процессах


Zend Memory Manager выделяет память большими блоками — чанки по ~2-4 МБ. Когда вы делаете unset($data) или переменная выходит из scope — память освобождается ВНУТРИ PHP, но операционная система об этом не узнаёт.

Чанки остаются закреплёнными за процессом до его завершения. Это сделано ради производительности: повторное использование уже выделенной памяти быстрее, чем постоянные запросы к ОС.

Почему это критично для RoadRunner, Laravel Queue, демонов?

В PHP-FPM каждый запрос = новый процесс, память автоматически очищается. В long-running процессах один worker обрабатывает тысячи задач — и каждый "пик" памяти становится новым baseline навсегда.

Ну а теперь про то, как себя обезопасить от всего этого?
- Использовать батчинг для выборок
- Ограничивать объём данных в памяти в рамках одной операции
- Обрабатывать данные потоково, без загрузки всего набора сразу
- Выносить тяжёлые операции в отдельные функции для автоматического освобождения локальных переменных
- Применять gc_mem_caches() для очистки внутренних пулов, и молиться, что поможет именно в вашем случае)
- Анализировать участки кода, создающие единовременные всплески в десятки МБ. Лучше не игнорировать всплески памяти, надеясь что “само освободится”

Что можно сделать на уровне PHP воркеров:
1. Можно использовать ротацию по количеству задач, например в RoadRunner pool.max_jobs=1000, Laravel Queue --max-jobs=1000. После выполнения 1000 задач, воркер будет перезапущен. Но не стоит полагаться на ротацию как на замену оптимизации, ведь пик может возникнуть в первых же запросах.
2. В RoadRunner — при необходимости включать soft-лимиты по памяти, при достижении которого воркер перезапускается.

Куда ещё может утекать память:
- Статические переменные, накапливающие данные
- Глобальные массивы, в которых растёт состояние
- Singleton-сервисы с неограниченными кешами
- ORM-кеши, которые не сбрасываются
- Списки подписчиков/слушателей, которые не удаляются
- Циклические ссылки объектов друг на друга.
1🔥46🤯109🤔2