🪤 Локальный дебаг-сервер без Docker
Ловить дампы через symfony/var-dumper можно, но ограниченно. SMTP, Sentry, Monolog, HTTP-дампы, Ray, бинарные данные — всё это мимо. buggregator/trap собирает всё в одну консоль.
Ставится:
Запускается:
Никакого Docker (написан целиком на PHP).
Функция trap() заменяет dump() и шлёт данные на локальный сервер:
Автоматически распознаёт тип трафика на одном порту, так что не нужно открывать отдельные пакеты для var-dumper, SMTP и Sentry. Есть шорткаты: tr() для дампа с возвратом, td() для дампа с die. Плагин для PhpStorm тоже в наличии.
🔗 Репозиторий на GitHub
🐸 Библиотека пхпшника
Ловить дампы через symfony/var-dumper можно, но ограниченно. SMTP, Sentry, Monolog, HTTP-дампы, Ray, бинарные данные — всё это мимо. buggregator/trap собирает всё в одну консоль.
Ставится:
composer require --dev buggregator/trap -W.
Запускается:
vendor/bin/trap.
Никакого Docker (написан целиком на PHP).
Функция trap() заменяет dump() и шлёт данные на локальный сервер:
trap($veryDeepArray)->depth(3);
trap($item)->times(3); // не больше 3 дампов
trap($response)->return(); // дампнуть и вернуть значение
Автоматически распознаёт тип трафика на одном порту, так что не нужно открывать отдельные пакеты для var-dumper, SMTP и Sentry. Есть шорткаты: tr() для дампа с возвратом, td() для дампа с die. Плагин для PhpStorm тоже в наличии.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤2👍1
В PHP 8.4 появилась долгожданная возможность — хуки свойств.
Это встроенная логика чтения и записи значения прямо в объявлении свойства. Без отдельных методов, без шаблонных getSomething() и setSomething(). Код становится компактнее, выразительнее и проще для сопровождения.
🔹 В чём была проблема
До этого было всего два варианта:
— классический подход с приватными полями и методами доступа;
— promoted-properties из конструктора — удобно, но без логики.
У обоих подходов есть ряд минусов:
— негде аккуратно разместить валидацию;
— сложно добавить логирование изменений;
— неудобно реализовать ленивые вычисления;
— класс быстро разрастался вспомогательными методами.
🔹 Что изменилось с хуками
Теперь PHP позволяет перехватывать:
→ момент чтения свойства;
→ момент записи значения.
При этом снаружи используется привычный доступ к свойству, внутри — чётко определённое место для логики и в одном классе можно сочетать обычные свойства и свойства с хуками.
🔹 Виртуальные свойства
PHP 8.4 позволяет создавать свойства без собственного хранилища.
Такие свойства:
→ не занимают память;
→ вычисляются при каждом обращении;
→ выступают как интерфейс к другим данным объекта.
Полезно для: объединённых представлений данных, вычисляемых значений, и упрощения публичного API модели.
— хуки несовместимы с readonly-свойствами;
— изменение по ссылке может обойти логику записи;
— не все внутренние функции PHP вызывают хуки одинаково.
🤖 Осталось 4 места на курс по ИИ-агентам. Набор закрывается 30 апреля.
🔗 Успеть на обучение
🔗 Хабр
Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1🔥1
🗓️ Уже через пару часов стартует вебинар!
Тема:
Ждем вас сегодня в 19:00 по московскому времени. Не пропустите начало, будет много практики!
👉 Успей занять место
Тема:
Как эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токены
Ждем вас сегодня в 19:00 по московскому времени. Не пропустите начало, будет много практики!
👉 Успей занять место
🌚2
⌨️ Топ-вакансий по PHP за неделю
PHP-разработчик — от 150 000 ₽ — удалёнка
Middle Backend Developer — от 170 000 до 230 000 р — удалёнка
PHP Backend — 150 000 – 400 000 ₽ — удалёнка
➡️ Еще больше топовых вакансий — в нашем канале PHP Jobs
PHP-разработчик — от 150 000 ₽ — удалёнка
Middle Backend Developer — от 170 000 до 230 000 р — удалёнка
PHP Backend — 150 000 – 400 000 ₽ — удалёнка
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1🔥1
Вот сколько общаюсь с разработчиками, постоянно слышу убеждение, что есть какой-то правильный способ писать софт. Все ищут секретную архитектуру, вылизывают паттерны, чтобы хоба и тимлид заплакал от счастья от твоего идеального кода.
но, я собрал 4 привычки адептов «чистого кода», (которые обычно все практикуют)
• Бесконечный рефакторинг рабочего кода.
Кажется, что так ты делаешь продукт лучше. Итог: жестко падаешь в перфекционизм. Переписываешь функцию по три раза, а бизнес ждет релиз. Закрываешь вкладку и в голове абсолютная пустота, время потрачено, а новых фичей ноль.
• Упарывание в сложную архитектуру
Сеньоры на ютубе обещают золотые горы, если внедрить микросервисы куда угодно. Итог: получаешь красивый overengineering-проект для мамы и 0 запущенных продуктов в срок, пока конкуренты клепают MVP на коленке.
• Душные споры на ревью
Неплохо, но как итог: ты пишешь полотна текста и тратишь часы на поиск глупой придирки к стилю, потому что банально фокус сместился с реальной задачи на эго.
• Ручная микро-оптимизация
Классика для тех, кто любит алгоритмы из универа. Итог: убиваешь дни жизни и выжимаешь миллисекунды, хотя бизнесу нужен был просто грязный, но рабочий скрипт еще вчера.
Проблема в том, что ни один из этих путей не дает самого главного - скорости и проверки гипотез. Реальному рынку плевать на твой идеальный код за 3 дня. Бизнес предпочтет код от ИИ-агента за 5 минут, который уже завтра начнет приносить деньги.
Хочешь обкатанный на нас лично и 100х учениках метод, как перестать кодить руками и начать делегировать задачи автономным системам?
P. S. Если интересно еще что-нибудь почитать от меня, то заходите в «Азбуку Айтишника», там я рассказываю об айти-базе, также у меня там есть бесплатный гайд на 15 глав по ии-агентам
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2😁2❤1💯1
Большинство статей про форматирование дат сводятся к таблице токенов. Но реальный вопрос не «какой символ за что отвечает», а когда использовать date(), а когда DateTimeImmutable.
🔹 date() для быстрых задач
echo date('Y-m-d H:i:s');
echo date('Y-m-d', 1710938096);Скрипты, логи, простой вывод — здесь date() вполне уместна. Она форматирует Unix timestamp, опираясь на системную timezone.
🔹 DateTimeImmutable для всего остального
$date = new DateTimeImmutable('2026-03-20 14:30:45', new DateTimeZone('Europe/Paris'));
echo $date->format('Y-m-d H:i:s T');
// 2026-03-20 14:30:45 CET
echo $date->setTimezone(new DateTimeZone('America/New_York'))->format('Y-m-d H:i:s T');
// 2026-03-20 09:30:45 EDTTimezone живёт внутри объекта, а не берётся из глобального контекста. Это критично, когда в проекте есть очереди, API, мультирегиональность или локаль пользователя.
🔹 date_format() просто обёртка
date_format($date, 'Y-m-d'); // то же самое, что $date->format('Y-m-d')Процедурный стиль для тех, кто не может расстаться с PHP 5-мышлением
🔹 Готовые форматы на каждый день
// Хранение в БД / логи
$date->format('Y-m-d H:i:s');
// ISO 8601 / API
$date->format('c'); // или DATE_ATOM
// Человекочитаемый
$date->format('d F Y'); // 20 March 2026
// 12-часовой формат
$date->format('g:i A'); // 2:30 PM
🔹 Экранирование в строке формата
Буквы a, t, m и другие — зарезервированные токены. Если нужен литерал, экранируй бэкслешем:
echo date('Y-m-d \a\t H:i', 1710938096);
// 2024-03-20 at 12:34Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍3🔥1
🔬 Лексер, парсер, интерпретатор — собираем свой DSL на чистом PHP
Doctrine DQL, Twig-выражения, Symfony ExpressionLanguage — всё это мини-языки внутри PHP-проектов. Под капотом у каждого одинаковый конвейер: исходный текст → токены → AST → результат.
Тот же конвейер ложится в 3 класса и ~150 строк, если задача — rule engine для бизнес-логики:
Парсер строит BinaryOpNode / UnaryOpNode, интерпретатор резолвит переменные через explode('.', $name) и match по операторам. Никакого eval — дерево объектов и рекурсия.
Расширяется под промокоды, скоринг, ACL и любые гибкие системы, где правила хранятся в БД как строки.
🔗 Читать оригинал — полный код всех трёх классов с тестами.
Библиотека пхпшника
#php_core
Doctrine DQL, Twig-выражения, Symfony ExpressionLanguage — всё это мини-языки внутри PHP-проектов. Под капотом у каждого одинаковый конвейер: исходный текст → токены → AST → результат.
Тот же конвейер ложится в 3 класса и ~150 строк, если задача — rule engine для бизнес-логики:
// Lexer: режет строку на токены через preg_match
// Parser: рекурсивный спуск → AST с приоритетами
// Interpreter: обход дерева + контекст
$rule = 'user.age >= 18 and (user.has_vip or user.orders_count > 5)';
$tokens = (new Lexer($rule))->getTokens();
$ast = (new Parser($tokens))->parse();
$result = (new Interpreter($context))->evaluate($ast);
// true | false — без eval, без магии
Парсер строит BinaryOpNode / UnaryOpNode, интерпретатор резолвит переменные через explode('.', $name) и match по операторам. Никакого eval — дерево объектов и рекурсия.
Расширяется под промокоды, скоринг, ACL и любые гибкие системы, где правила хранятся в БД как строки.
🔗 Читать оригинал — полный код всех трёх классов с тестами.
Библиотека пхпшника
#php_core
👍2❤1👏1
🧪 Тестирование Symfony-конфигов
Библиотека matthiasnoback/symfony-config-test предоставляет PHPUnit-трейт с готовыми ассертами для проверки дерева конфигурации. Она позволяет убедиться, что конфиги ведут себя корректно при невалидных данных, мёрже и дефолтах:
Через параметр breadcrumbPath можно тестировать отдельную ветку дерева (например, doctrine.orm), игнорируя остальные required-ноды. Версия 6.x поддерживает PHPUnit 10–12.
Репозиторий на GitHub
Библиотека пхпшника
#release_radar
Библиотека matthiasnoback/symfony-config-test предоставляет PHPUnit-трейт с готовыми ассертами для проверки дерева конфигурации. Она позволяет убедиться, что конфиги ведут себя корректно при невалидных данных, мёрже и дефолтах:
class ConfigurationTest extends TestCase
{
use ConfigurationTestCaseTrait;
protected function getConfiguration(): Configuration
{
return new Configuration();
}
public function test_invalid(): void
{
$this->assertConfigurationIsInvalid(
[[]], // пустой массив
'required_value'
);
}
public function test_processed(): void
{
$this->assertProcessedConfigurationEquals(
[['key' => 'first'], ['key' => 'last']],
['key' => 'last']
);
}
}
Через параметр breadcrumbPath можно тестировать отдельную ветку дерева (например, doctrine.orm), игнорируя остальные required-ноды. Версия 6.x поддерживает PHPUnit 10–12.
Репозиторий на GitHub
Библиотека пхпшника
#release_radar
👍2🔥1
🏗 Laravel SaaS: как не утонуть в собственном коде через полгода
Дефолтная структура Laravel отлично заходит на старте. Потом приходят мультитенантность, биллинг, сложные правила. В итоге контроллеры пухнут, логика расползается по моделям и джобам.
Рабочий рецепт: модульный монолит с доменной организацией. Каждый домен — мини-приложение внутри приложения.
💡 Правила, которые реально экономят часы на рефакторинге:
— контроллер принимает FormRequest, дёргает сервис, возвращает Resource;
— бизнес-логика живёт в сервисах, чтобы переиспользоваться в API, CLI и очередях;
— доступ к БД — через репозитории, без Booking::where() в сервисах;
— сразу версионируй API (/api/v1), иначе первый же breaking change принесёт боль.
По SaaS-специфике: Sanctum для SPA, Cashier + Stripe для подписок (писать биллинг руками — плохая идея), stancl/tenancy если нужна изоляция тенантов. Тяжёлое отправляем в очереди на Redis, дебаг с Telescope локально и Sentry в проде.
🔗 Читать оригинал
Библиотека пхпшника
#book_code
Дефолтная структура Laravel отлично заходит на старте. Потом приходят мультитенантность, биллинг, сложные правила. В итоге контроллеры пухнут, логика расползается по моделям и джобам.
Рабочий рецепт: модульный монолит с доменной организацией. Каждый домен — мини-приложение внутри приложения.
app/Domains/Bookings/
Models/
Services/
Repositories/
DTOs/
Actions/
Requests/
💡 Правила, которые реально экономят часы на рефакторинге:
— контроллер принимает FormRequest, дёргает сервис, возвращает Resource;
— бизнес-логика живёт в сервисах, чтобы переиспользоваться в API, CLI и очередях;
— доступ к БД — через репозитории, без Booking::where() в сервисах;
— сразу версионируй API (/api/v1), иначе первый же breaking change принесёт боль.
По SaaS-специфике: Sanctum для SPA, Cashier + Stripe для подписок (писать биллинг руками — плохая идея), stancl/tenancy если нужна изоляция тенантов. Тяжёлое отправляем в очереди на Redis, дебаг с Telescope локально и Sentry в проде.
🔗 Читать оригинал
Библиотека пхпшника
#book_code
🔥8👍3❤2😁2👾1
Forwarded from Библиотека собеса по PHP | вопросы с собеседований
Баг не воспроизводится локально. На проде один юзер видит чужие данные 👇
📦 Задание
Стартап запустил SaaS. Первые две недели тишина. А потом в поддержку прилетело: «Я зашёл в кабинет и увидел чужой аккаунт». В коде сессий и авторизации не трогали давно, там всё стабильно.
// src/Auth/UserSession.php
class UserSession
{
private static ?User $currentUser = null;
public static function set(User $user): void
{
self::$currentUser = $user;
}
public static function get(): ?User
{
return self::$currentUser;
}
public static function clear(): void
{
self::$currentUser = null;
}
}
// src/Middleware/AuthMiddleware.php
class AuthMiddleware
{
public function __construct(
private readonly UserRepository $userRepository,
private readonly JWTService $jwt,
) {}
public function handle(Request $request, callable $next): Response
{
$token = $request->headers->get('Authorization');
if (!$token) {
return new Response(status: 401);
}
$payload = $this->jwt->decode(str_replace('Bearer ', '', $token));
$user = $this->userRepository->find($payload['sub']);
UserSession::set($user);
return $next($request);
}
}
// src/Controller/DashboardController.php
class DashboardController
{
public function index(): Response
{
$user = UserSession::get();
return new Response(
body: $this->renderDashboard($user),
);
}
}
// src/Console/CacheWarmupCommand.php
class CacheWarmupCommand
{
public function execute(): void
{
$users = $this->userRepository->findAll();
foreach ($users as $user) {
UserSession::set($user);
$this->warmupForUser($user);
}
// прогрев завершён
}
}
🔹 Задачи
— Объяснить механизм утечки
— Объяснить, как CacheWarmupCommand триггерит баг и при каком race window
— Переписать UserSession так, чтобы устранить проблему архитектурно, а не патчем
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍3❤2🤔1
🏭 PHP дотянулся до промышленных PLC
Исторически связать PHP с OPC UA (протокол SCADA, контроллеров Siemens, датчиков Industry 4.0) означало городить шлюз на Python/Node, тащить C-расширения через FFI или звать внешние процессы из шелла. Костыли, латенси, второй стек в проде.
Проект php-opcua закрывает этот разрыв — нативная реализация бинарного протокола OPC UA на чистом PHP. Ноль C-зависимостей кроме ext-openssl.
Что в экосистеме:
— opcua-client: транспорт, крипто (10 security policies, включая ECC), сессии, подписки;
— opcua-session-manager: ReactPHP-демон держит сессию живой, хендшейк 150мс → 5мс на запрос;
— laravel-opcua и symfony-opcua: фасады, DI, события, кеш через Redis/PSR-16;
— opcua-client-nodeset: 807 сгенерённых DTO из 51 companion spec (Robotics, CNC, ISA-95).
Три строки и Eloquent-модель читает температуру с цеха. Без сайдкаров.
🔗 Подробнее
Библиотека пхпшника
Исторически связать PHP с OPC UA (протокол SCADA, контроллеров Siemens, датчиков Industry 4.0) означало городить шлюз на Python/Node, тащить C-расширения через FFI или звать внешние процессы из шелла. Костыли, латенси, второй стек в проде.
Проект php-opcua закрывает этот разрыв — нативная реализация бинарного протокола OPC UA на чистом PHP. Ноль C-зависимостей кроме ext-openssl.
Что в экосистеме:
— opcua-client: транспорт, крипто (10 security policies, включая ECC), сессии, подписки;
— opcua-session-manager: ReactPHP-демон держит сессию живой, хендшейк 150мс → 5мс на запрос;
— laravel-opcua и symfony-opcua: фасады, DI, события, кеш через Redis/PSR-16;
— opcua-client-nodeset: 807 сгенерённых DTO из 51 companion spec (Robotics, CNC, ISA-95).
$client = ClientBuilder::create()
->connect('opc.tcp://192.168.1.100:4840');
$temp = $client->read('ns=2;s=Temperature');
echo $temp->getValue(); // 23.5
Три строки и Eloquent-модель читает температуру с цеха. Без сайдкаров.
🔗 Подробнее
Библиотека пхпшника
👍12🔥6💯1
Forwarded from Библиотека задач по PHP | тесты, код, задания
Что будет результатом кода?
Anonymous Quiz
24%
Применяем скидку!
23%
Скидка недоступна. Итого: 29
49%
Скидка недоступна. Итого: 28.999999999999
3%
fatal error
😁7🤔4👍3🔥2
🦾 Почему ваши AI-продукты на базе LLM ломаются (и как это чинить)?
Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало».
🗓️ Когда: 14 мая в 19:00 МСК
⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы
🧑🏻💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы.
🎁 Главный бонус для онлайна:
Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps.
👉 Занять место на вебинаре
Выкатили ИИ-фичу в прод, а она галлюцинирует, падает или выдает мусор? Приглашаем на открытый вебинар, где разберем реальную боль внедрения LLM-агентов и научимся делать так, чтобы «всё работало».
🗓️ Когда: 14 мая в 19:00 МСК
⏱️ Формат: 60 минут мяса + 30 минут ответов на ваши вопросы
🧑🏻💻 Кто вещает: Эмиль Сатаев — Backend Platform Developer (8+ лет в разработке). Человек, который своими руками внедряет LLM и агентные системы в реальные коммерческие сервисы.
🎁 Главный бонус для онлайна:
Только участникам прямого эфира подарим уникальный промокод на скидку 10.000 ₽ на большой курс AgentOps.
👉 Занять место на вебинаре
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🥱3🔥1😁1🤔1
⌨️ Топ-вакансий по PHP за неделю
PHP/Vue.js Developer — офис (Москва) — TRIBE
PHP и Node.js разработчик — от 1000 до 2500 $ — удалёнка
РНР-разработчик (Авто.ру Бизнес) — 200 000 — 300 000 ₽ — гибрид (Москва, Санкт-Петербург )
➡️ Еще больше топовых вакансий — в нашем канале PHP Jobs
PHP/Vue.js Developer — офис (Москва) — TRIBE
PHP и Node.js разработчик — от 1000 до 2500 $ — удалёнка
РНР-разработчик (Авто.ру Бизнес) — 200 000 — 300 000 ₽ — гибрид (Москва, Санкт-Петербург )
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1👍1