Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
10.8K subscribers
1.65K photos
27 videos
26 files
4.44K links
Все самое полезное для пхпшника в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/bca892d6

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b
Download Telegram
⌨️ Топ-вакансий по PHP за неделю

Fullstack разработчик PHP — от 180 000 до 230 000 ₽ — удалёнка

Backend-разработчик — от 1 800 до 3 100 $ — удалёнка

Team Lead PHP — до 402 000 ₽ — удалёнка

➡️ Еще больше топовых вакансий — в нашем канале PHP Jobs
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
⚡️ Laravel: withCount() вместо with() для агрегатов

with('orders') подгружает всю коллекцию моделей в память. Если нужна только цифра — это избыточно.

Антипаттерн

$users = User::with('orders')->get();
// Eloquent грузит все связанные модели в память
// затем PHP считает count() на уже загруженной коллекции

foreach ($users as $user) {
echo $user->orders->count();
}


Правильно

$users = User::withCount('orders')->get();
// Генерирует подзапрос: SELECT count(*) as orders_count
// Один SQL-запрос, ноль лишних объектов в памяти

foreach ($users as $user) {
echo $user->orders_count;
}


Доступные хелперы одного семейства:
User::withSum('orders', 'total')    // orders_sum_total
User::withAvg('reviews', 'rating') // reviews_avg_rating
User::withMin('orders', 'total') // orders_min_total
User::withMax('orders', 'total') // orders_max_total


Каждый из них транслируется в коррелированный подзапрос.
А цепочка из нескольких всё равно будет одни основным SELECT'ом.

Применимо когда:

— рендеришь список с агрегированными метриками;
— строишь API без лишних аллокаций;
— профилируешь и видишь with() там, где нужна только цифра.
6👍4🔥1🥱1
🔥 База по ИИ-агентам от научного сотрудника Сколтеха и НИУ ВШЭ

Знакомьтесь, Екатерина Трофимова. Кандидат компьютерных наук, ресерчер в Центре ИИ Сколтеха и лаборатории LAMBDA. Она объединяет глубокую академическую экспертизу и практику: знает, как ИИ-системы устроены «под капотом» и как встроить их в реальные проекты (в т.ч. для Т-банка).

Мы попросили Екатерину собрать список мастхев материалов для тех, кто хочет проектировать агентов в проде. Сохраняйте список.

🛠 Стек и фреймворки:

DSPy — алгоритмическая оптимизация промптов (вместо ручного подбора слов).

Semantic Kernel и LangMem — инструменты для управления сессионной и долгосрочной памятью.

MCP (Model Context Protocol) — новый стандарт от Anthropic для подключения агентов к вашим БД и локальным файлам.

📖 Документация, которую нужно знать:

Anthropic Prompt Caching — как кэшировать контекст и радикально резать косты на API.

OpenAI Agents SDK / Cookbook — лучшие практики работы с памятью.

Augment — платформа для оптимизации работы ИИ-агентов и контроля токенов.

🔬 Хардкорные статьи и препринты (на выходные):

Lost in the Middle — почему LLM «слепнут» на длинных текстах и забывают середину контекста.

How Do Coding Agents Spend Your Money? — куда улетает бюджет при работе автономных кодинг-агентов.

MemGPT — архитектура операционной системы для LLM с иллюзией бесконечной памяти.

InjecAgent / AgentSentry — всё о безопасности и защите агентов от инъекций в промпты.

Екатерина Трофимова — один из ключевых экспертов нашего курса AgentOps. На своих лекциях она детально разбирает, как проектировать инструменты для агентов, как агент принимает решения о вызове инструментов и какие ограничения возникают в реальном проде

🎁 Акция в честь старта продаж!

Прямо сейчас при покупке Инженерного трека вы получаете полный доступ к материалам курса «Разработка ИИ-агентов» в подарок.

👉 Забрать 2 курса по цене 1 и начать обучение
1
💬 Обратная связь

Коллеги, давайте соберём базу годных ресурсов по PHP помимо нашего канала.

✔️ Присылайте в комменты:

— Блоги и статьи
— Telegram-каналы
— YouTube-каналы и подкасты
— Репозитории
— Доклады

Что НЕ ищем

Курсы "php с нуля за месяц", базовые туториалы и переводы официальной документации.

💬 Закидывайте в комменты ваши любимые источники. Для работы, для учёбы, для повседневного чтения.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔4🔥1
🔧 array_key_first() / array_key_last()

Помните, как все делали reset() или array_keys($arr)[0], чтобы получить первый ключ? Начиная с PHP 7.3 есть нативный способ:

php//  старый способ
$key = array_keys($data)[0];

// чистый нативный
$key = array_key_first($data);
$last = array_key_last($data);

// работает с ассоциативными тоже
$map = ['foo' => 1, 'bar' => 2];
array_key_first($map); // 'foo'


Не мутирует массив (в отличие от reset()), не создаёт лишний массив ключей — просто возвращает ключ или null если массив пустой.

🔥 Пока разбираетесь с массивами — параллельно можно освоить ИИ-агентов. 4 места до 30 апреля.

🐸 Библиотека пхпшника

#vardump
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍1
🪤 Локальный дебаг-сервер без Docker

Ловить дампы через 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 тоже в наличии.

🔗 Репозиторий на GitHub

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥92👍1
👀 Хуки свойств в PHP

В 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
🗓️ Уже через пару часов стартует вебинар!

Тема:
Как эффективно управлять контекстным окном LLM в мультиагентных системах и не сливать бюджет на токены


Ждем вас сегодня в 19:00 по московскому времени. Не пропустите начало, будет много практики!

👉 Успей занять место
🌚2
⌨️ Топ-вакансий по PHP за неделю

PHP-разработчик — от 150 000 ₽ — удалёнка

Middle Backend Developer — от 170 000 до 230 000 р — удалёнка

PHP Backend — 150 000 – 400 000 ₽ — удалёнка

➡️ Еще больше топовых вакансий — в нашем канале PHP Jobs
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1🔥1
🔥 4 привычки кодеров

Вот сколько общаюсь с разработчиками, постоянно слышу убеждение, что есть какой-то правильный способ писать софт. Все ищут секретную архитектуру, вылизывают паттерны, чтобы хоба и тимлид заплакал от счастья от твоего идеального кода.

но, я собрал 4 привычки адептов «чистого кода», (которые обычно все практикуют) 🤡

• Бесконечный рефакторинг рабочего кода.
Кажется, что так ты делаешь продукт лучше. Итог: жестко падаешь в перфекционизм. Переписываешь функцию по три раза, а бизнес ждет релиз. Закрываешь вкладку и в голове абсолютная пустота, время потрачено, а новых фичей ноль.

• Упарывание в сложную архитектуру

Сеньоры на ютубе обещают золотые горы, если внедрить микросервисы куда угодно. Итог: получаешь красивый overengineering-проект для мамы и 0 запущенных продуктов в срок, пока конкуренты клепают MVP на коленке.

• Душные споры на ревью
Неплохо, но как итог: ты пишешь полотна текста и тратишь часы на поиск глупой придирки к стилю, потому что банально фокус сместился с реальной задачи на эго.

• Ручная микро-оптимизация
Классика для тех, кто любит алгоритмы из универа. Итог: убиваешь дни жизни и выжимаешь миллисекунды, хотя бизнесу нужен был просто грязный, но рабочий скрипт еще вчера.

Проблема в том, что ни один из этих путей не дает самого главного - скорости и проверки гипотез. Реальному рынку плевать на твой идеальный код за 3 дня. Бизнес предпочтет код от ИИ-агента за 5 минут, который уже завтра начнет приносить деньги.

Хочешь обкатанный на нас лично и 100х учениках метод, как перестать кодить руками и начать делегировать задачи автономным системам?

👉 Заходи сюда, но у нас осталось всего 4 места, набор идет до завтрашнего дня.

P. S. Если интересно еще что-нибудь почитать от меня, то заходите в «Азбуку Айтишника», там я рассказываю об айти-базе, также у меня там есть бесплатный гайд на 15 глав по ии-агентам
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2😁21💯1
🗓 Когда date() достаточно, а когда нет

Большинство статей про форматирование дат сводятся к таблице токенов. Но реальный вопрос не «какой символ за что отвечает», а когда использовать 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 EDT


Timezone живёт внутри объекта, а не берётся из глобального контекста. Это критично, когда в проекте есть очереди, 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:34
Please 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 для бизнес-логики:

// 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
👍21👏1
🧪 Тестирование Symfony-конфигов

Библиотека 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 отлично заходит на старте. Потом приходят мультитенантность, биллинг, сложные правила. В итоге контроллеры пухнут, логика расползается по моделям и джобам.

Рабочий рецепт: модульный монолит с доменной организацией. Каждый домен — мини-приложение внутри приложения.

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👍32😁2👾1
✔️ 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👍32🤔1