ar
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

إظهار المزيد

📈 نظرة تحليلية على قناة تيليجرام Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

تُعد قناة Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter (@phpproglib) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 10 705 مشتركاً، محتلاً المرتبة 11 598 في فئة التكنولوجيات والتطبيقات والمرتبة 61 274 في منطقة روسيا.

📊 مؤشرات الجمهور والحراك

منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 10 705 مشتركاً.

بحسب آخر البيانات بتاريخ 05 يونيو, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -34، وفي آخر 24 ساعة بمقدار -1، مع بقاء الوصول العام مرتفعاً.

  • حالة التحقق: غير موثّقة
  • معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 15.28‎%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 9.13‎% من ردود الفعل نسبةً إلى إجمالي المشتركين.
  • وصول المنشورات: يحصل كل منشور على متوسط 1 637 مشاهدة. وخلال اليوم الأول يجمع عادةً 978 مشاهدة.
  • التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 11.
  • الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل php, laravel, пхпшника, artisan, api.

📝 الوصف وسياسة المحتوى

يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b

بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 06 يونيو, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.

10 705
المشتركون
-124 ساعات
-97 أيام
-3430 أيام
أرشيف المشاركات
✔️ PHP-тест: клон, который мутирует оригинал Пользователь нажал «Повторить заказ». Цены в его старом заказе изменились. 📦 Задание Фича: кнопка «Повторить заказ» в личном кабинете. Копирует предыдущий заказ, применяет промокод, создаёт новый черновик. Оригинал помечается флагом repeated для аналитики. Через неделю — тикет от бухгалтерии: суммы в старых заказах не сходятся с тем, что было при оплате. Проблема только у заказов, которые хотя бы раз «повторяли». Суммы занижены ровно на размер скидки по промокоду.
// src/Order/Order.php
class Order
{
    public function __construct(
        private ?int   $id,
        private int    $userId,
        private array  $items, 
        private string $status,
        private bool   $repeated = false,
    ) {}

    public function getId(): ?int      { return $this->id; }
    public function getItems(): array  { return $this->items; }
    public function getStatus(): string { return $this->status; }

    public function resetForRepeat(): void
    {
        $this->id       = null;
        $this->status   = 'draft';
        $this->repeated = false;
    }

    public function markAsRepeated(): void
    {
        $this->repeated = true;
    }

    public function calculateTotal(): int
    {
        return array_sum(array_map(
            fn(OrderItem $i) => $i->getSubtotal(),
            $this->items
        ));
    }
}

// src/Order/OrderItem.php
class OrderItem
{
    public function __construct(
        private int $productId,
        private int $qty,
        private int $price,
    ) {}

    public function getProductId(): int { return $this->productId; }
    public function getQty(): int       { return $this->qty; }
    public function getPrice(): int     { return $this->price; }

    public function getSubtotal(): int
    {
        return $this->qty * $this->price;
    }

    public function applyDiscount(int $percent): void
    {
        $this->price = (int) round(
            $this->price * (1 - $percent / 100)
        );
    }
}

// src/Order/RepeatOrderHandler.php
class RepeatOrderHandler
{
    public function __construct(
        private OrderRepository $orders,
        private PromoService    $promo,
    ) {}

    public function handle(int $originalId, ?string $promoCode): Order
    {
        $original = $this->orders->findById($originalId);

        $copy = clone $original;
        $copy->resetForRepeat();

        if ($promoCode !== null) {
            $discount = $this->promo->resolve($promoCode);

            foreach ($copy->getItems() as $item) {
                $item->applyDiscount($discount->percent);
            }
        }

        $this->orders->save($copy);

        $original->markAsRepeated();
        $this->orders->save($original);

        return $copy;
    }
}

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

    public function save(Order $order): void
    {
        if ($order->getId() === null) {
            $this->insert($order);
        } else {
            $this->update($order);
        }
    }

    private function update(Order $order): void
    {
        $this->pdo->prepare(
            'UPDATE orders SET status = ?, repeated = ? WHERE id = ?'
        )->execute([$order->getStatus(), (int) $order->isRepeated(), $order->getId()]);

        $this->pdo->prepare('DELETE FROM order_items WHERE order_id = ?')
            ->execute([$order->getId()]);

        foreach ($order->getItems() as $item) {
            $this->pdo->prepare(
                'INSERT INTO order_items (order_id, product_id, qty, price) VALUES (?, ?, ?, ?)'
            )->execute([$order->getId(), $item->getProductId(), $item->getQty(), $item->getPrice()]);
        }
    }
}
🔹 Задачи — Объяснить, каким образом цены в оригинальном заказе оказались изменены в базе — Исправить код так, чтобы оригинал гарантированно не мутировал Ставьте → 🔥 если нравится формат. Если нет → 🌚 💬 Решения пишите в комменты под спойлер — сравним подходы.

💡 Затрагиваемые отношения Eloquent Laravel автоматически обновляет updated_at в ManyToMany отношениях, а также поставляется
💡 Затрагиваемые отношения Eloquent Laravel автоматически обновляет updated_at в ManyToMany отношениях, а также поставляется с методом setTouchedRelations для ручного обновления связанных моделей в отношениях OneToOne и OneToMany. 🐸 Библиотека пхпшника #vardump

Письмо ушло, но воркер упал до того как пометил job выполненной. Job запустилась повторно, что получит пользователь?
Anonymous voting

🧑‍💻 Приглашаем на открытый урок курса «PHP-разработчик. Продвинутый уровень» 19 мая в 20:00 — Работа с очередями в Laravel:
🧑‍💻 Приглашаем на открытый урок курса «PHP-разработчик. Продвинутый уровень» 19 мая в 20:00 — Работа с очередями в Laravel: от настройки до решения типичных проблем Разберём, как очереди помогают ускорить приложение и вынести тяжёлые задачи в фон без потери стабильности. Обсудим настройку и обработку задач, типичные ошибки, повторы при сбоях, защиту от дублирования и мониторинг выполнения. Вы поймёте, как работают фоновые процессы в Laravel, научитесь правильно настраивать очереди и делать приложение быстрее и надёжнее. 🚀Открытый урок проходит в преддверии старта курса «PHP-разработчик. Продвинутый уровень» 19 мая в 20:00 МСК. Регистрация: https://clc.to/v1jqRw Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

🔽 Ловим тормозные запросы до того, как это сделает прод Метод whenQueryingForLongerThan позволяет задать порог в миллисекундах и среагировать моментально: кинуть алерт в Slack, залогировать или просто позвать автора запроса на кофе.
// AppServiceProvider::boot()

DB::whenQueryingForLongerThan(500, function (Connection $connection, QueryExecuted $event) {
    Log::warning('Slow query detected', [
        'sql'  => $event->sql,
        'time' => $event->time,
    ]);

    // Notification::send(...);
});
⏱️ Порог считается для суммарного времени всех запросов на соединении, а не для одиночного (для точечного мониторинга есть DB::listen()).

📌 backup PostgreSQL с минимальной нагрузкой на прод Разберём эффективный способ бэкапа PostgreSQL с помощью pg_basebackup + реплики. Сценарий: есть продовый PostgreSQL и настроенная горячая реплика (streaming replication). Зачем использовать реплику для бэкапа? ▪️ Причины — На проде бэкап может замедлить отклик приложения. — Реплика отличный способ разгрузить основной сервер. — Бэкап с pg_basebackup возможен только на стопнутой БД или через репликацию. ▪️ Как сделать
pg_basebackup -h replica.host -U repl_user -D /backup/pg -F tar -z -P
▪️ Флаги -h — адрес реплики -U — пользователь с правами репликации -D — куда класть бэкап -F tar -z — формат архива и сжатие -P — прогресс в консоли А ещё можно добавить в cron и получить стабильный ночной бэкап.

🔥 Знакомьтесь с экспертом Proglib.academy: Эмиль Сатаев Эмиль — эксперт с 8-летним опытом в разработке, который специализиру
🔥 Знакомьтесь с экспертом Proglib.academy: Эмиль Сатаев Эмиль — эксперт с 8-летним опытом в разработке, который специализируется на внедрении LLM и агентных подходов в реальные коммерческие сервисы. Он точно знает, как проектировать архитектуру так, чтобы ИИ-функции работали стабильно в связке с внешними системами. 🏃‍♀️ Уже 14 мая Эмиль проведет открытый вебинар! Обсудим самую «больную» тему: «Почему AI-продукты на базе LLM ломаются и как сделать, чтобы работало». 🗓 Когда: 14 мая в 19:00 (Мск) Почему Эмиля стоит послушать: 🟣 8+ лет в разработке (Backend и Frontend)
Прошел путь от фулстека до Backend Platform Developer в SMIT.Studio.
🟣 Международный исследовательский опыт
Работал исследователем в Институте ИИ НИУ ВШЭ и в Национальном университете Сингапура (NUS).
🟣 Преподаватель-практик
Ведет семинары в НИУ ВШЭ, в том числе по проектированию и разработке агентских систем.
🟣 Мастер интеграции AI в Backend
Его главная суперсила — умение правильно встраивать LLM через API, выстраивать workflow и агентную логику в сложных распределенных системах.
🔗 Зарегистрироваться на вебинар

🧠 LLPhant: LangChain для PHP-разработчиков Если нужно прикрутить LLM к проекту, а городить мост на Python в виде отдельного сервиса не хочется — LLPhant закрывает эту задачу одной либой. Это единый интерфейс к OpenAI, Anthropic, Mistral, LM Studio и локальным моделям через Ollama.
// Сегодня OpenAI
$chat = new OpenAIChat();
$response = $chat->generateText('Столица Франции?');

// Завтра — локальная модель
$config = new OllamaConfig();
$config->model = 'llama2';
$chat = new OllamaChat($config);
Что внутри: — полноценный RAG-пайплайн: чтение PDF/Word, чанкинг, эмбеддинги, поиск; — векторные хранилища на любой вкус — pgvector, Redis, Elastic, Qdrant, Milvus, Pinecone; — стриминг ответов, подсчет токенов, vision для картинок; — function calling — описываешь тулзы PHP-классами, модель сама решит когда дернуть. Для смены провайдера нужно переписать две строки в конфиге (а не половину сервиса). 🔗 Подробнее Библиотека пхпшника

⚡️ Магия curl Сервис отвечает 500-кой, а вы не понимаете — проблема в сети, DNS, SSL или бэкенд лёг? Прежде чем лезть в логи и разворачивать Wireshark, попробуйте curl -w и получите полный таймлайн запроса за секунду. 🔹 Зачем это нужно — Разбивает запрос на фазы: DNS, TCP-коннект, TLS-хендшейк, ожидание первого байта, передача данных. — Моментально показывает, где именно bottleneck — на уровне сети или приложения. — Работает везде: на проде, в контейнере, на CI-раннере. 🔹 Как использовать — Полный таймлайн запроса:
curl -o /dev/null -s -w "\n  DNS: %{time_namelookup}s\n  TCP: %{time_connect}s\n  TLS: %{time_appconnect}s\n  TTFB: %{time_starttransfer}s\n  Total: %{time_total}s\n" https://your-api.com/health
— Если time_namelookup высокий, проблема в DNS, смотрите резолвер. — Если между time_connect и time_appconnect большой разрыв, тормозит TLS, проверяйте сертификаты. — Если time_starttransfer зашкаливает при нормальном коннекте, бэкенд думает слишком долго. — Удобно завернуть в алиас и дёргать по крону для бедняцкого мониторинга latency. 💡 Про-тип: сохраните шаблон в файл и вызывайте через curl -w имя_файла. Не придётся каждый раз гуглить формат переменных.

📊 Аналитика поведения: 5 инструментов, которые стоит знать Гуглишь «best analytics tools» и получаешь кашу из BI-дашбордов, product analytics и session replay в одной куче. Разложу по полочкам именно поведенческую аналитику и конкурентную разведку — то, что реально нужно, когда задача «понять, почему юзеры не конвертятся». Hotjar — безопасный дефолт. Хитмапы, записи сессий, фидбек-виджеты. Порог входа минимальный, поэтому его ставят первым и часто на нём остаются. Если нужно быстро показать продакту «вот тут юзеры отваливаются» — закроет задачу. Но если серьёзно копаете конверсии, ему начинает не хватать глубины. Mouseflow — для тех, кто реально сидит в записях и воронках. Friction score, form analytics, 6 типов хитмап (включая geo и live). По CRO и e-commerce — пожалуй, самый сильный вариант. Подвох: кредитные лимиты и капы на объём сессий начинают кусаться при росте трафика. Crazy Egg — максимально простой. Хитмапы, скроллмапы, оверлеи. Не нужна глубокая аналитика, нужно за 15 минут понять, куда кликают и докуда скроллят — это оно. Kissmetrics — другая лига. Event-level аналитика, retention, lifecycle. Заточен под SaaS с логин-зоной, где важен путь конкретного юзера, а не агрегированные хитмапы. Overhead на внедрение ощутимый, комьюнити вокруг инструмента тоньше, чем у Hotjar. Similarweb — вообще не про ваш сайт, а про чужие. Бенчмарки трафика, каналы, доли рынка. Цифры направляющие, не абсолютные — относитесь как к компасу, не как к GPS.

🧹 Git-команда, которая спасёт ваш репозиторий от мусора Проблема: вы удалили ветки, сделали git reset, отменили мёржи, но репозиторий почему-то весит всё больше. git clone на новом месте занимает вечность. Куда уходит место? Дело в том, что Git — барахольщик. Он хранит все объекты: старые блобы, недостижимые коммиты, забытые stash'ы. Даже то, что вам давно не нужно. 💡 Решение: git gc и его старший брат git gc --aggressive Рассмотрим все все возможности git gc. 1️⃣ Сколько мусора накопилось
git count-objects -vH
Обратите внимание на size-pack — это реальный вес вашего репо. 2️⃣ Самые тяжёлые объекты в истории
git rev-list --objects --all \
  | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
  | awk '/^blob/ {print $3, $4}' \
  | sort -rn \
  | head -10
Часто находятся артефакты сборки, дампы БД или случайно закоммиченные .jar на 200 МБ 😬 3️⃣ Запустите агрессивную сборку мусора
git gc --aggressive --prune=now
--aggressive заставляет Git перепаковать объекты с нуля, а --prune=now удаляет недостижимые объекты немедленно, не дожидаясь дефолтных двух недель. 4️⃣ Сравните результат
git count-objects -vH
На живых проектах с историей в 2+ года разница бывает в разы. ⚠️ --prune=now безвозвратно удалит объекты, на которые нет ссылок. Если вы планировали восстановить что-то через git reflog — сделайте это до запуска.

✔️ PHP-тест: Идемпотентность, которой нет Пользователь нажал «Оплатить» один раз. Деньги списались дважды. 📦 Задание Фича: интеграция с платёжным шлюзом. Платёж создаётся на бэке, пользователь редиректится на страницу шлюза, после оплаты шлюз дёргает webhook. По webhook'у выдаётся доступ к продукту. Жалобы начались через две недели после релиза. Только у части пользователей, только в часы пик. У некоторых списывалось дважды, у других доступ не выдавался вовсе.
// src/Payment/WebhookHandler.php
class WebhookHandler
{
    public function __construct(
        private PaymentRepository $payments,
        private OrderRepository   $orders,
        private AccessService     $access,
        private Mailer            $mailer,
    ) {}

    public function handle(array $payload): void
    {
        $externalId = $payload['payment_id'];
        $status     = $payload['status'];

        if ($status !== 'success') {
            return;
        }

        $payment = $this->payments->findByExternalId($externalId);

        if ($payment === null) {
            return;
        }

        $order = $this->orders->findById($payment->orderId);

        if ($order->status === 'paid') {
            return;
        }

        $this->orders->markAsPaid($payment->orderId);
        $this->access->grantForOrder($order);
        $this->mailer->sendReceipt($order);
    }
}

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

    public function findById(int $id): Order
    {
        $stmt = $this->pdo->prepare(
            'SELECT * FROM orders WHERE id = ?'
        );
        $stmt->execute([$id]);
        return Order::fromRow($stmt->fetch(PDO::FETCH_ASSOC));
    }

    public function markAsPaid(int $orderId): void
    {
        $stmt = $this->pdo->prepare(
            'UPDATE orders SET status = ? WHERE id = ?'
        );
        $stmt->execute(['paid', $orderId]);
    }
}
🔹 Задачи — Объяснить, как именно возникает двойное списание при одном нажатии пользователя — Исправить WebhookHandler::handle Ставьте → 🔥 если нравится формат. Если нет → 🌚 💬 Решения пишите в комменты под спойлер — сравним подходы.

🗓 14 мая в 19:00 (Мск) встречаемся в онлайне. Тема: Почему AI-продукты на базе LLM ломаются и как сделать, чтобы работало. В кружке выше Эмиль Сатаев рассказал, какие именно проблемы с LLM в проде будем разбирать. Что в программе:
- Разберем реальные кейсы стартапов и ограничения LLM. - Обсудим рабочие архитектуры: RAG, human-in-the-loop, контроль качества. - Ответим на ваши вопросы и разберем кейсы участников.
🎁 Бонусы: в конце вебинара подарим промокод на скидку 10.000 ₽ на курсы и разыграем подписки на полезные AI-сервисы. 👉 Зарегистрироваться на вебинар

رسالة فيديو00:40

🔼 Улучши UX одним методом При создании опций для CLI-приложений можно улучшить UX, реализовав автозаполнение для пользовател
🔼 Улучши UX одним методом При создании опций для CLI-приложений можно улучшить UX, реализовав автозаполнение для пользователя. Это можно сделать с помощью метода anticipate, предоставляемого Laravel 🚀 Библиотека пхпшника #vardump

Как правильно определять границы сервисов в микросервисной архитектуре? Один из недооценённых скиллов в разработке — это умение провести правильную границу между сервисами. Большинство «распределённых монолитов», которые мы встречаем в продакшене, рождаются именно здесь. Разобрали тему — держи шпаргалку 👇 🔹 Что такое Service Boundary Это контракт на три вещи: — за что сервис отвечает; — какими данными он владеет; — как он общается с соседями. Пример: в компании HR не лезет в финансы, а склад не занимается зарплатами. Так же должны работать твои сервисы. 🔹 4 принципа, которые работают 1. Business Capability First Режь по бизнес-функциям, а не по техническим слоям. OrderService, PaymentService, UserService — потому что именно так бизнес думает о системе. 2. Single Responsibility Один сервис — одна ответственность. Если в описании сервиса есть союз «и», это уже тревожный звоночек 🚨 3. Data Ownership У каждого сервиса своя БД. Без исключений. Shared database = shared pain. 4. Loose Coupling Только API, никакого прямого доступа к чужим таблицам. 🔹 Классический антипаттерн
// ❌ Бизнес-логика смешана в одном сервисе
class BadOrderService
{
    public function processOrderAndPayment(int $id): string
    {
        $order = $this->orderRepository->findById($id)
            ?? 'Order not found';

        $paymentStatus = 'Payment Successful'; // 🚨 чужая ответственность

        return $order . ' | ' . $paymentStatus;
    }
}
Выглядит безобидно, пока не нужно масштабировать платежи отдельно, сменить платёжного провайдера или добавить retry-логику только для оплаты. Тут и начнутся реальные проблемы. 🔹 Советы из практикиНачни с монолита. Не дроби систему заранее. Сначала пойми домен, потом режь по швам. → Следи за chatty communication. Если сервис делает 10 вызовов к соседям на каждый запрос — граница явно проведена не там. → Изучи DDD. Bounded Context из Domain-Driven Design — лучший инструмент для поиска правильных границ. Инвестиция окупается быстро. 💬 Делимся в комментах страшными историями god-сервисов