Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b
Ko'proq ko'rsatish📈 Telegram kanali Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter analitikasi
Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter (@phpproglib) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 10 698 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 11 609-o'rinni va Rossiya mintaqasida 61 312-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 10 698 obunachiga ega bo‘ldi.
09 Iyun, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -40 ga, so‘nggi 24 soatda esa 0 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 15.51% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 8.98% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 1 659 marta ko‘riladi; birinchi sutkada odatda 961 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 11 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent php, laravel, пхпшника, artisan, api kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Все самое полезное для пхпшника в одном канале.
По рекламе: @proglib_adv
Учиться у нас: https://proglib.io/w/bca892d6
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 10 Iyun, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
composer require pestphp/pest --dev
composer require pestphp/pest-plugin-laravel --dev
php artisan pest:install
После этого в корне появится tests/Pest.php — файл для глобальных хелперов и настроек. Не игнорируй его.
✍️ Шаг 2 — Первый тест
Забудь про классы. Pest — это функции:
it('создаёт пользователя через API', function () {
$response = $this->postJson('/api/users', [
'name' => 'Ivan',
'email' => 'ivan@example.com',
]);
$response->assertCreated();
expect($response->json('data.name'))->toBe('Ivan');
});
🧩 Шаг 3 — Datasets (параметризованные тесты)
Вместо копипасты одного теста на каждый кейс:
it('валидирует email', function (string $email) {
$response = $this->postJson('/api/users', [
'email' => $email
]);
$response->assertUnprocessable();
})->with([
'пустой' => [''],
'без собаки' => ['notanemail'],
'только домен' => ['@example.com'],
]);
⚙️ Шаг 4 — Глобальные настройки в Pest.php
Открываем tests/Pest.php и настраиваем раз и навсегда:
uses(
Tests\TestCase::class,
Illuminate\Foundation\Testing\RefreshDatabase::class,
)->in('Feature');
expect()->extend('toBeSuccess', function () {
return $this->toMatchArray([
'status' => 'success'
]);
});
Теперь RefreshDatabase не нужно писать в каждом файле, а кастомные матчеры делают тесты выразительнее.
🚀 Шаг 5 — Запуск
./vendor/bin/pest
./vendor/bin/pest --filter="создаёт пользователя"
./vendor/bin/pest --coverage # требует Xdebug или PCOV
💡 Почему Pest, а не чистый PHPUnit?
Меньше бойлерплейта, человекочитаемый вывод, встроенные архитектурные тесты (arch()) и отличная интеграция с Laravel. Команда Laravel официально рекомендует его с 11-й версии фреймворка.
Ставьте 🔥 если используете Pest.docker stats
— Конкретный сервис: docker stats my-spring-app
— Один снимок без стриминга: docker stats --no-stream
— Только нужные поля: docker stats --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"
— В JSON для скриптов: docker stats --no-stream --format json
Флаг --format принимает Go-шаблоны — те же, что и в docker inspect. Можно вывести ровно то, что нужно, и скормить в jq или свой мониторинг-скрипт.
⚠️ Если контейнер запущен без -m / --memory, JVM видит всю память хоста и выставляет heap соответственно. docker stats мгновенно покажет, есть ли лимит — колонка MEM USAGE / LIMIT.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,
) {}
}
🔹 Задачи
— Найти все источники роста памяти
— Объяснить, почему проблема не воспроизводится на стейджинге
— Предложить решение
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.
Endi mavjud! Telegram Tadqiqoti 2025 — yilning asosiy insaytlari 
