Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
Все самое полезное для пхпшника в одном канале. По рекламе: @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),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
Python и современных фреймворков. Мы не будем учить «общаться» с нейросетью, мы будем строить из неё надёжный инструмент.
✅ Что вы получите:
— понимание того, как управлять логикой агента на уровне кода;
— навыки работы с LangChain и библиотеками оркестрации;
— готовые паттерны для обработки ошибок и галлюцинаций;
— опыт создания систем, которые реально экономят время.
Есть пара мест со скидкой до завтра, решайтесь 👈🏻// 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
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.// Читаемо и быстро
Cache::get('user:' . $id);
// Явно и тестируемо
public function __construct(
private CacheInterface $cache,
) {}
Скрытые зависимости, нарушение SRP, привязка к фреймворку через __callStatic() — звучит страшно. Но 64% PHP-девов используют Laravel и не парятся.
Как пишете вы — Facades или DI? И считаете ли, что Тейлор красиво «продал» антипаттерн?
💬 Пишите ваше мнение в комментарии
#междусобойчик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 позволяет их «изменить» без рефлексии.
#vardumpsymfony/translation, разберём подходы к хранению переводов, варианты моделей данных и практическую реализацию получения локализованного содержимого через Doctrine.
Урок не для тех, кто хочет решить многоязычность «одной таблицей на всё», не думает о поддержке архитектуры и считает, что локализация заканчивается на переводе кнопок и заголовков.👉 Записаться: https://clc.to/x9D9Pg Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
// 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, это его дизайн. Просто решай осознанно.
🐸 Библиотека пхпшника
#элементарный_выбор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// 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,
) {}
}
🔹 Задачи
— Найти все источники роста памяти
— Объяснить, почему проблема не воспроизводится на стейджинге
— Предложить решение
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.LangGraph, извлечение данных из кривых сканов для RAG и комплаенс по 152-ФЗ.
Если всё ещё сомневаетесь, послушайте голосовое от спикера курса Влада Прошинского, где он объясняет, как правильно тестировать агентов перед релизом.Программа курса, полный состав спикеров и другие подробности 👈🏻 ВАЖНО! До 5 апреля на курс действует скидка, но свободные места могут закончиться раньше.
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 скрывает инфраструктуру, а не просто переносит запросы в другой файл.
🐸 Библиотека пхпшника
#элементарный_выбор
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
