ch
Feedback
Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

前往频道在 Telegram

Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b

显示更多

📈 Telegram 频道 Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter 的分析概览

频道 Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter (@phpproglib) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 10 699 名订阅者,在 技术与应用 类别中位列第 11 619,并在 俄罗斯 地区排名第 61 433

📊 受众指标与增长动态

невідомо 创建以来,项目保持高速增长,吸引了 10 699 名订阅者。

根据 07 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -47,过去 24 小时变化为 -7,整体触达仍然可观。

  • 认证状态: 未认证
  • 互动率 (ER): 平均受众互动率为 15.28%。内容发布后 24 小时内通常能获得 9.03% 的反应,占订阅者总量。
  • 帖子覆盖: 每篇帖子平均可获得 1 635 次浏览,首日通常累积 966 次浏览。
  • 互动与反馈: 受众积极参与,单帖平均反应数为 10
  • 主题关注点: 内容集中在 php, laravel, пхпшника, artisan, api 等核心主题上。

📝 描述与内容策略

作者将该频道定位为表达主观观点的平台:
Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b

凭借高频更新(最新数据采集于 08 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。

10 699
订阅者
-724 小时
-197
-4730
帖子存档
🤯 Представьте, что ваш AI-агент работает так же предсказуемо, как обычный микросервис. Звучит утопически, но это именно то, к чему должна прийти разработка в 2026 году. Основная боль текущих реализаций — полная непредсказуемость поведения. Сегодня агент выполнил задачу за два шага, а завтра ушёл в рекурсию и потратил все лимиты. Наш обновлённый курс «Разработка AI-агентов» научит, как приручить этот хаос с помощью Python и современных фреймворков. Мы не будем учить «общаться» с нейросетью, мы будем строить из неё надёжный инструмент. ✅ Что вы получите: — понимание того, как управлять логикой агента на уровне кода; — навыки работы с LangChain и библиотеками оркестрации; — готовые паттерны для обработки ошибок и галлюцинаций; — опыт создания систем, которые реально экономят время. Есть пара мест со скидкой до завтра, решайтесь 👈🏻

🤔 Разрабатываете ИИ-агентов, но всё ещё не уверены в их стабильности и прогнозируемости? Мы поговорили с десятками разработчиков ИИ-агентов и сделали отдельный курс по AgentOps. 🧠 На нём вы узнаете: – как оптимизировать траты на токены; – как на практике оценить качество работы агента; – как «докручивать» RAG-системы без потери качества; – как обеспечить устойчивость агента к сбоям внешних сервисов без падения всей системы и про многое-многое другое. 📅 Старт: 19 мая. 👥 Спикеры — практики с опытом в AI и Data Science в крупных IT-компаниях, таких как Яндекс, Huawei, МТС и др. Длительность: 6-12 недель в зависимости от тарифа. 🔗 Программа курса и другие подробности

✔️ PHP-тест: Race condition Код прошёл нагрузочное тестирование. На проде деньги задвоились 👇 📦 Задание Фича: пользователь может переводить бонусные баллы другу. Логика простая — проверить баланс, списать, начислить. Тесты зелёные, нагрузочное прогнали — всё ок. Через три дня после релиза: у нескольких пользователей баланс ушёл в минус, у других — задвоился.
// src/Bonus/BonusTransferService.php
class BonusTransferService
{
    public function __construct(
        private PDO            $pdo,
        private BonusRepository $repo,
    ) {}

    public function transfer(int $fromId, int $toId, int $amount): void
    {
        $this->pdo->beginTransaction();

        try {
            $fromBalance = $this->repo->getBalance($fromId);

            if ($fromBalance < $amount) {
                throw new InsufficientFundsException();
            }

            $this->repo->debit($fromId, $amount);
            $this->repo->credit($toId, $amount);

            $this->pdo->commit();

        } catch (Throwable $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }
}

// src/Bonus/BonusRepository.php
class BonusRepository
{
    public function __construct(private PDO $pdo) {}

    public function getBalance(int $userId): int
    {
        $stmt = $this->pdo->prepare(
            'SELECT balance FROM bonus_accounts WHERE user_id = ?'
        );
        $stmt->execute([$userId]);
        return (int) $stmt->fetchColumn();
    }

    public function debit(int $userId, int $amount): void
    {
        $stmt = $this->pdo->prepare(
            'UPDATE bonus_accounts SET balance = balance - ? WHERE user_id = ?'
        );
        $stmt->execute([$amount, $userId]);
    }

    public function credit(int $userId, int $amount): void
    {
        $stmt = $this->pdo->prepare(
            'UPDATE bonus_accounts SET balance = balance + ? WHERE user_id = ?'
        );
        $stmt->execute([$amount, $userId]);
    }
}
🔹 Задачи — Объяснить, как именно происходит race condition в этом коде — Почему транзакция здесь не защищает от проблемы — Исправить getBalance так, чтобы устранить race condition Ставьте → 🔥 если нравится формат. Если нет → 🌚 💬 Решения пишите в комменты под спойлер — сравним подходы.

🔥 Laravel Facades красота или костыль?
// Читаемо и быстро
Cache::get('user:' . $id);

// Явно и тестируемо
public function __construct(
    private CacheInterface $cache,
) {}
Скрытые зависимости, нарушение SRP, привязка к фреймворку через __callStatic() — звучит страшно. Но 64% PHP-девов используют Laravel и не парятся. Как пишете вы — Facades или DI? И считаете ли, что Тейлор красиво «продал» антипаттерн? 💬 Пишите ваше мнение в комментарии #междусобойчик

⚙️ readonly свойства + clone в PHP 8.4 Классика: у тебя Value Object с readonly-свойствами, и нужно вернуть копию с одним изменённым полем. До 8.4 приходилось делать фабричный метод вручную:
class Money {
    public function __construct(
        public readonly int    $amount,
        public readonly string $currency,
    ) {}

    public function withAmount(int $amount): static
    {
        return new static($amount, $this->currency);
    }
}
В PHP 8.4 появился clone with:
$price = new Money(1000, 'USD');

$discounted = clone $price with {
    amount: 850,
};
Никаких withField() методов на каждый чих. clone with работает даже с readonly — это единственное место, где PHP позволяет их «изменить» без рефлексии. #vardump

Локализация текстов в Symfony: от статических переводов к динамическим данным из базы. Бесплатный урок курса «Symfony Framewo
Локализация текстов в Symfony: от статических переводов к динамическим данным из базы. Бесплатный урок курса «Symfony Framework» Перевести интерфейс через файлы — это только начало. Настоящие сложности начинаются тогда, когда переводить нужно не статичные строки, а содержимое из базы данных, которое живёт в административной панели, меняется редакторами и должно оставаться управляемым с точки зрения архитектуры. 📅 На открытом уроке 15 апреля в 20:00: — Разберём реальный сценарий локализации в Symfony — от стандартного подхода со статическими переводами до более сложной работы с динамическими текстами из базы данных. — Покажем возможности компонента symfony/translation, разберём подходы к хранению переводов, варианты моделей данных и практическую реализацию получения локализованного содержимого через Doctrine.
Урок не для тех, кто хочет решить многоязычность «одной таблицей на всё», не думает о поддержке архитектуры и считает, что локализация заканчивается на переводе кнопок и заголовков.
👉 Записаться: https://clc.to/x9D9Pg Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

⚡️ Почему Redis такой быстрый Стандартный ответ — «потому что in-memory». Это правда, но не объяснение. Куча баз данных хранит данные в памяти и не показывает таких цифр. Настоящий ответ в другом: каждое архитектурное решение Redis убирает конкретный источник latency. 🧵 Один поток Redis обрабатывает команды последовательно в один поток. Никаких мьютексов, никакого context switching. Тысячи соединений при этом обслуживаются через epoll/kqueue — один поток следит за всеми сокетами через I/O multiplexing и не блокируется ни на одном из них. 📦 Адаптивные структуры Hash с небольшим числом ключей хранится не как хэш-таблица, а как listpack — плотный байтовый массив, который влезает в один cache line. Никаких pointer chasing. Только когда данных становится много, Redis переключается на полноценную хэш-таблицу. Sorted Set — одновременно хэш-таблица и skiplist. O(1) по ключу и O(log N) для range-запросов без второго прохода. 💾 fork() Снапшот RDB пишется дочерним процессом после fork(). Благодаря CoW основной процесс продолжает работу и не видит никакой паузы — ОС копирует только изменённые страницы памяти. AOF идёт дальше и логирует каждую команду, давая возможность восстановиться до последней записи. Точнее, но дороже — компромисс осознанный. 🧹 bounded expiry Ключи с истёкшим TTL удаляются двумя способами: лениво при обращении и активно — каждые 100 мс Redis сэмплирует случайную выборку и чистит просроченные. Если таких больше 25%, повторяет цикл. Это не O(N) по всей базе, а предсказуемая нагрузка с жёстким потолком по CPU. Redis — это не «база данных в памяти». Это система, где каждый выбор — однопоток, listpack, fork(), bounded expiry — существует потому, что альтернатива добавляла latency. In-memory здесь просто необходимое условие, а не причина скорости.

🧭 Разбираем современный PHP вместе с Podlodka PHP Crew PHP-стек может устаревать незаметно: решения вроде бы работают, но ск
🧭 Разбираем современный PHP вместе с Podlodka PHP Crew PHP-стек может устаревать незаметно: решения вроде бы работают, но скорость разработки снижается, стоимость поддержки растёт, а количество возможностей сокращается. 💡 Эксперты Podlodka PHP Crew собрали онлайн-конференцию «Современный стек PHP-разработки», чтобы разобраться, как всё устроено сегодня. 🗓С 20 по 24 апреля участники: • изучат, как сегодня запускают PHP-приложения (worker mode, новые рантаймы, FrankenPHP), • посмотрят, как изменилась инфраструктура и что пора выкинуть из Docker-стека, • обсудят, как реально применять AI-агентов в разработке (не только писать код, но и расследовать баги и планировать изменения), • разберут практические кейсы (например, в онлайн-режиме будут запускать мультиплеерную игру на PHP с Temporal и RoadRunner), • и в целом поймут, какие инструменты и подходы действительно стоит внедрять в 2026. Формат — пять дней живых Zoom-сессий по утрам и вечерам, закрытое комьюнити в Telegram и общение со спикерами. Если хотите обновить свой стек и лучше понимать, куда движется разработка на PHP — обязательно присоединяйтесь👇 🎟Early-bird билеты доступны до 13 апреля А по промокоду php_crew_8_1wcIhz получите скидку🎁

Какой признак характерен для архитектуры CQRS?
Anonymous voting

📊 Doctrine vs Eloquent Их сравнивают как два способа работать с БД. На самом деле это два разных взгляда на то, что такое доменная модель. Eloquent — Active Record. Модель знает о базе данных. Она сама сохраняет себя, сама удаляет, сама строит запросы. Это удобно и это цена: бизнес-логика и слой персистентности перемешаны с рождения.
// Eloquent — модель и есть запись в таблице
$user = User::where('email', $email)->firstOrFail();
$user->status = 'active';
$user->save();
Doctrine — Data Mapper. Модель ничего не знает о БД. EntityManager знает, как сохранить объект. Объект остаётся чистым PHP-классом.
// Doctrine — модель не знает про persist
$user = $this->repository->findByEmail($email);
$user->activate(); // метод в домене, не save()
$this->em->flush();
✔️ Где Eloquent выигрывает — CRUD-приложения, где домен тонкий — Быстрый старт, меньше конфигурации — Команда знакома с Laravel — не надо учить новый mental model Где Eloquent начинает мешать — Сложные агрегаты с инвариантами — Хочешь тестировать доменную логику без БД — Один объект — несколько таблиц или наоборот ✔️ Где Doctrine оправдан — Богатая доменная модель (DDD, агрегаты, value objects) — Нужна полная изоляция домена от инфраструктуры — Сложные маппинги, наследование, polymorphic relations с контролем Главный сигнал: если ты ловишь себя на том, что пишешь методы в Eloquent-модели, которые делают $this->save() — домен начинает протекать. Это не баг Eloquent, это его дизайн. Просто решай осознанно. 🐸 Библиотека пхпшника #элементарный_выбор

🔒 Prepared statements Prepared statements защищают от инъекций. Но также их можно осознанно использовать для оптимизации. Когда вы выполняете один и тот же запрос в цикле — БД каждый раз парсит и строит план выполнения заново. Плохо:
foreach ($userIds as $id) {
    $pdo->query("SELECT * FROM users WHERE id = $id"); // парсинг + план на каждой итерации
}
Хорошо — prepare один раз, execute много раз:
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
 
foreach ($userIds as $id) {
    $stmt->execute([':id' => $id]);
    $user = $stmt->fetch();
}
БД кеширует план выполнения запроса\. На 10 000 итераций разница ощутима\. Ещё лучше — batch-запрос:
$placeholders = implode(',', array_fill(0, count($userIds), '?'));
$stmt = $pdo->prepare("SELECT * FROM users WHERE id IN ($placeholders)");
$stmt->execute($userIds);
$users = $stmt->fetchAll();
// Один запрос вместо N
Библиотека пхпшника #vardump

✔️ PHP-тест: Generators + Memory leak + Batch-обработка «Мы перешли на генераторы, чтобы не грузить память» — но память всё равно растёт 👇 📦 Задание Команда переписала импорт CSV на генераторы — раньше падало с OOM на файлах больше 500 МБ. После рефакторинга память перестала расти... на стейджинге. На проде с реальными файлами на 2M+ строк потребление всё равно ползёт вверх.
// src/Import/CsvImporter.php
class CsvImporter
{
    private array $processedIds = [];
    private array $errors       = [];
    private int   $totalRows    = 0;

    public function import(string $filePath): ImportResult
    {
        foreach ($this->readRows($filePath) as $row) {
            $this->totalRows++;

            try {
                $id = $this->processRow($row);
                $this->processedIds[] = $id;
            } catch (RowException $e) {
                $this->errors[] = [
                    'row'     => $this->totalRows,
                    'message' => $e->getMessage(),
                    'data'    => $row,
                ];
            }
        }

        return new ImportResult($this->processedIds, $this->errors, $this->totalRows);
    }

    private function readRows(string $filePath): \Generator
    {
        $handle = fopen($filePath, 'r');
        $headers = fgetcsv($handle);

        while (($raw = fgetcsv($handle)) !== false) {
            yield array_combine($headers, $raw);
        }

        fclose($handle);
    }

    private function processRow(array $row): int
    {
        // Валидация, маппинг, вставка в БД
        // Возвращает inserted ID
        return $this->repository->upsert($row);
    }
}

// src/Import/ImportResult.php
class ImportResult
{
    public function __construct(
        public readonly array $processedIds,
        public readonly array $errors,
        public readonly int   $totalRows,
    ) {}
}
🔹 Задачи — Найти все источники роста памяти — Объяснить, почему проблема не воспроизводится на стейджинге — Предложить решение Ставьте → 🔥 если нравится формат. Если нет → 🌚 💬 Решения пишите в комменты под спойлер — сравним подходы.

📊 Queue vs Cron Оба инструмента про «выполнить что-то не прямо сейчас». Но они решают разные задачи, и смешивать их не стоит. Cron — планировщик. Он про время. «Запусти это в 03:00». «Запусти каждые 5 минут». Ему всё равно, что именно запускать — он просто триггерит процесс по расписанию. Queue — очередь. Она про события и нагрузку. «Отправь письмо, когда пользователь зарегистрировался». «Обработай 10 000 строк CSV асинхронно». Очередь не знает про время, она знает про задачи. 🔹 Где Cron уместен — Агрегация данных за период (ночные отчёты) — Очистка устаревших записей — Синхронизация с внешним источником по расписанию — Задачи, которые должны выполняться независимо от пользовательской активности 🔹 Где Queue уместен — Всё, что пользователь спровоцировал, но ждать не должен — Задачи с потенциальными ретраями (внешний API может упасть) — Параллельная обработка (несколько воркеров) — Отправка уведомлений, генерация файлов, вебхуки Если ты пишешь cron-задачу, которая ищет записи со статусом "pending" — ты уже строишь очередь. Используй нормальную: Redis + Laravel Horizon, RabbitMQ, SQS, Beanstalkd. Комбинация: cron запускает job, который кладёт задачи в очередь. Это нормально — диспетчер по расписанию и обработчики асинхронно. 🐸 Библиотека пхпшника #элементарный_выбор

✌🏻 У нас две новости — хорошая и плохая! Хорошая: Ваших знаний, скорее всего, хватит, чтобы собрать рабочую демку AI-агента в Colab. 🫡 Плохая: Вы вряд ли выведете его в прод, не обанкротившись на токенах и не слив базу. 🤯 Для защиты от таких сценариев мы полностью пересобрали курс «Разработка AI-агентов». Теперь внутри плотная работа с экономикой ресурсов, дебаг через time-travel в LangGraph, извлечение данных из кривых сканов для RAG и комплаенс по 152-ФЗ.
Если всё ещё сомневаетесь, послушайте голосовое от спикера курса Влада Прошинского, где он объясняет, как правильно тестировать агентов перед релизом.
Программа курса, полный состав спикеров и другие подробности 👈🏻 ВАЖНО! До 5 апреля на курс действует скидка, но свободные места могут закончиться раньше.

⌨️ Топ-вакансий по PHP за неделю PHP разработчик - от 150 000 до 200 000 ₽ - удалёнка Senior Fullstack PHP разработчик - от 250 000 до 350 000 ₽ - удалёнка Lead PHP Developer - до 400 000 ₽ - удалёнка ➡️ Еще больше топовых вакансий — в нашем канале PHP Jobs

📊 Repository Pattern vs Query Builder Repository — это не про «обернуть Eloquent в класс». Это про то, что доменный код не должен знать, откуда берутся данные. Плохой Repository, который можно часто встретить:
class UserRepository {
    public function findActive(): Collection {
        return User::where('status', 'active')->get();
    }
 
    public function findByEmailAndStatus(string $email, string $status): ?User {
        return User::where('email', $email)
                   ->where('status', $status)
                   ->first();
    }
    // ...ещё 40 методов под каждый запрос
}
Это не Repository — это коллекция запросов в обёртке. Домен по-прежнему диктует методы через свои нужды, а репозиторий распухает. Хороший Repository работает с агрегатами и скрывает детали хранения:
interface UserRepository {
    public function findById(UserId $id): ?User;
    public function findByEmail(Email $email): ?User;
    public function save(User $user): void;
    public function remove(User $user): void;
}
Всё остальное — спецификации, критерии, query objects. Или честный Query Builder там, где это не домен. Где Query Builder напрямую оправдан: — Read-модели (CQRS: команды через домен, запросы — прямо в БД) — Отчёты, дашборды, агрегации — там нет смысла гидрировать объекты — Простые CRUD-экраны без доменной логики
// Это нормально для read-модели
$stats = DB::table('orders')
    ->selectRaw('status, COUNT(*) as count, SUM(amount) as total')
    ->groupBy('status')
    ->get();
Пытаться пропустить это через Repository с Order-сущностями — оверинжиниринг. Правило: Repository живёт на границе домена. Если у тебя нет домена, нет смысла в Repository. Если домен есть, Repository скрывает инфраструктуру, а не просто переносит запросы в другой файл. 🐸 Библиотека пхпшника #элементарный_выбор