Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: clc.to/M561SQ Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b
إظهار المزيد📈 نظرة تحليلية على قناة تيليجرام Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
تُعد قناة Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter (@phpproglib) في القطاع اللغوي الروسية لاعباً نشطاً. يضم المجتمع حالياً 10 522 مشتركاً، محتلاً المرتبة 11 314 في فئة التكنولوجيات والتطبيقات والمرتبة 60 447 في منطقة روسيا.
📊 مؤشرات الجمهور والحراك
منذ تأسيسه في невідомо، حقق المشروع نمواً سريعاً وجمع 10 522 مشتركاً.
بحسب آخر البيانات بتاريخ 26 أغسطس, 2026، تحافظ القناة على نشاط مستقر. خلال آخر 30 يوماً تغيّر عدد الأعضاء بمقدار -63، وفي آخر 24 ساعة بمقدار -1، مع بقاء الوصول العام مرتفعاً.
- حالة التحقق: غير موثّقة
- معدل التفاعل (ER): يبلغ متوسط تفاعل الجمهور 19.12%. وخلال أول 24 ساعة من النشر يحصد المحتوى عادةً 9.47% من ردود الفعل نسبةً إلى إجمالي المشتركين.
- وصول المنشورات: يحصل كل منشور على متوسط 2 012 مشاهدة. وخلال اليوم الأول يجمع عادةً 997 مشاهدة.
- التفاعلات والاستجابة: يتفاعل الجمهور بانتظام؛ متوسط التفاعلات لكل منشور يبلغ 15.
- الاهتمامات الموضوعية: يركز المحتوى على مواضيع رئيسية مثل php, laravel, пхпшника, artisan, api.
📝 الوصف وسياسة المحتوى
يصف المؤلف القناة بأنها مساحة للتعبير عن الآراء الذاتية:
“Все самое полезное для пхпшника в одном канале.
По рекламе: @proglib_adv
Учиться у нас: clc.to/M561SQ
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b”
بفضل وتيرة التحديث المرتفعة (أحدث البيانات بتاريخ 27 أغسطس, 2026) تحافظ القناة على حداثتها ومستوى وصول مرتفع. وتُظهر التحليلات تفاعلاً نشطاً من الجمهور، ما يجعلها نقطة تأثير مهمة ضمن فئة التكنولوجيات والتطبيقات.
$query = User::query();
if ($request->has('active')) {
$query->where('active', true);
}
if ($request->has('role')) {
$query->where('role', $request->role);
}
$users = $query->get();
У Eloquent есть when() и он делает это элегантно:
$users = User::query()
->when($request->has('active'), fn($q) => $q->where('active', true))
->when($request->role, fn($q, $role) => $q->where('role', $role))
->get();
Второй аргумент when() — это значение условия, оно же автоматически передаётся третьим параметром в колбэк. Не нужно захватывать переменную через use.
Используй это для фильтрации по параметрам запроса, построения поисковых форм и любых условных скоупов. Код становится читаемым как pipeline, а не лестница из if-else.
⚠️ Ловушка: when('0', ...) — не выполнится, потому что '0' приводится к false. Если важна строка "0" — проверяй явно: when($val !== null, ...).
Библиотека пхпшника
#vardump$ cat inventory.csv | column -t -s,
Флаг -s указывает на использование запятых в качестве разделителей, а -t форматирует выходные данные в чистую таблицу.
📍 Навигация: Вакансии • Задачи • Вопросы с собесаclass MerchantContext
{
private static ?string $currentMerchantId = null;
public static function set(string $id): void
{
self::$currentMerchantId = $id;
}
public static function get(): ?string
{
return self::$currentMerchantId;
}
public static function clear(): void
{
self::$currentMerchantId = null;
}
}
class WebhookProcessor
{
public function handle(WebhookPayload $payload): void
{
MerchantContext::set($payload->merchantId);
$fiber = new Fiber(function () use ($payload): void {
$result = $this->validateSignature($payload);
// симулируем I/O — запрос к внешнему сервису
Fiber::suspend();
$this->auditLogger->log(
'Webhook processed for: ' . MerchantContext::get(),
['amount' => $payload->amount]
);
});
$fiber->start();
// ... другие файберы запускаются здесь
$fiber->resume();
}
}
🔹 Задачи
— Объяснить, почему MerchantContext::get() после resume() может вернуть merchant_id другого запроса
— Исправить так, чтобы контекст не терялся при переключении между файберами
Ставьте → 🔥 если нравится формат. Если нет → 🌚
💬 Решения пишите в комменты под спойлер — сравним подходы.// Переименовал параметр — и где-то тихо упало
function createUser(string $name, bool $isActive): void {}
createUser(name: 'Ivan', active: true); // Fatal
Имя параметра теперь публичный контракт. Rector, IDE-рефакторинг, переименование в наследнике — всё это теперь breaking change.
💬 А вы юзаете named arguments в публичном API или только внутри?
Библиотека пхпшника
#междусобойчик// ❌ Часто вижу
define('APP_START', microtime(true));
// ... где-то в конце
$elapsed = microtime(true) - APP_START;
// ✅ Уже есть
$elapsed = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
Разница принципиальная. APP_START фиксирует момент после автозагрузки, DI-контейнера и прочего bootstrap'а. REQUEST_TIME_FLOAT — реальный старт запроса на уровне PHP-FPM.
// Логируй реальное время ответа в footer или middleware
header('X-Response-Time: ' . round(
(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2
) . 'ms');
⚠️ Ловушки
— В CLI REQUEST_TIME_FLOAT есть, но равен моменту запуска скрипта.
— Не путай с REQUEST_TIME (int, секунды) — для замеров он бесполезен.
Библиотека пхпшника
#vardump// Переименовал параметр — и где-то тихо упало
function createUser(string $name, bool $isActive): void {}
createUser(name: 'Ivan', active: true); // Fatal
Имя параметра теперь публичный контракт. Rector, IDE-рефакторинг, переименование в наследнике — всё это теперь breaking change.
💬 А вы юзаете named arguments в публичном API или только внутри?
Библиотека пхпшника
#междусобойчик// User.php
public function posts(): HasMany
{
return $this->hasMany(Post::class);
}
// Post.php
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
Всё. Laravel сам догадается, что posts.user_id ссылается на users.id — по соглашению об именовании. Теперь можно писать читаемый код:
// Все посты пользователя
$user->posts;
// Автор конкретного поста
$post->user->name;
// Посты только опубликованные
$user->posts()->where('published', true)->get();
Никаких JOIN-ов вручную. Никакого WHERE user_id = ?. Ты работаешь с объектами, а не с сырым SQL.
Три связи, которые покрывают 90% случаев
▪️ hasMany — у пользователя много постов
▪️ belongsTo — пост принадлежит пользователю
▪️ belongsToMany — пост имеет много тегов, тег стоит на многих постах (промежуточная таблица)
Связи — это просто способ сказать Laravel: «вот как мои таблицы соотносятся». Дальше он разберётся сам.
Библиотека пхпшника
#php_азбука// ❌ Было
if ($score >= 90) {
$grade = 'A';
} elseif ($score >= 75) {
$grade = 'B';
} elseif ($score >= 60) {
$grade = 'C';
} else {
$grade = 'F';
}
// ✅ Стало
$grade = match(true) {
$score >= 90 => 'A',
$score >= 75 => 'B',
$score >= 60 => 'C',
default => 'F',
};
Читается сверху вниз, возвращает значение, не требует break.
💡 match использует строгое сравнение (===), а при отсутствии default бросает UnhandledMatchError. Всегда добавляй default если входные данные непредсказуемы.
🐸 Библиотека пхпшника«А почему мы вообще используем именно это?»Чаще всего ответ → «так исторически сложилось». Но давай разберём более делательно. 🔹 MySQLi — быстрый, но привязанный Работает только с MySQL/MariaDB. Зато даёт нативные async-запросы через mysqli_poll(), что редкость, но иногда критично.
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
Синтаксис bind_param с типами — это боль при большом числе параметров.
🔹 PDO — абстракция с характером
Поддерживает 12+ драйверов: MySQL, PostgreSQL, SQLite, MSSQL, и др. Именованные плейсхолдеры — читаемость на уровне:
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id AND role = :role");
$stmt->execute(['id' => $id, 'role' => $role]);
Одна нотация везде. Смена БД без переписывания логики запросов.
📊 Что реально важно на проекте
Смена БД когда-либо → PDO (без вариантов)
Legacy MySQL-проект → MySQLi уже там, не трогай
Нужен fetchAll в объекты → PDO::FETCH_CLASS чище
Производительность → разница < 1%, забудь
💡 Вердикт
MySQLi — это не "плохо". Это инструмент под конкретный стек.
Но если ты стартуешь проект с нуля или пишешь библиотеку, то лучше PDO. Любой ORM (Doctrine, Eloquent) под капотом использует именно его.
🐸 Библиотека пхпшника
#элементарный_выборfunction process(int|string $id): User|null {
// ...
}
Раньше это документировали только в PHPDoc и надеялись на лучшее.
🔹 mixed, never, void
▪️ mixed — явно говорит "любой тип", в отличие от отсутствия типа
▪️ never — функция никогда не вернёт управление (бросает исключение или завершает процесс)
▪️ void — функция ничего не возвращает
function redirect(string $url): never {
header("Location: $url");
exit();
}
🔹 Intersection Types (8.1)
Значение должно реализовывать все указанные интерфейсы одновременно:
function process(Serializable&Countable $data): void {
// ...
}
Полезно при работе с коллекциями и DTO, которые соответствуют нескольким контрактам.
🔹 Enums (8.1)
Наконец-то нативные перечисления вместо констант в классах:
enum Status: string {
case Active = 'active';
case Inactive = 'inactive';
}
function setStatus(Status $status): void { ... }
Теперь нельзя передать произвольную строку туда, где ожидается Status.
🔹 Readonly properties (8.1) и readonly классы (8.2)
class User {
public function __construct(
public readonly int $id,
public readonly string $name,
) {}
}
В 8.2 можно пометить весь класс как readonly — все свойства автоматически становятся иммутабельными. Отлично подходит для Value Objects и DTO.
🔹 DNF Types — Disjunctive Normal Form (8.2)
Комбинация union и intersection:
function handle(Countable&Iterator|null $collection): void {
// ...
}
Тип читается как: "реализует оба интерфейса, либо null".
🔹 typed class constants (8.3)
class Config {
const string VERSION = '1.0.0';
const int MAX_RETRIES = 3;
}
До 8.3 константы классов не имели типов — теперь контракт полный.
⚠️ Нюансы
— declare(strict_types=1) обязателен, иначе PHP будет тихо приводить типы и "5" пройдёт там, где ожидается int
— Intersection types не работают с примитивами только с интерфейсами и классами
— readonly нельзя применить к static свойствам
— Enums не поддерживают наследование
Библиотека пхпшника$matrix = [[1, 2, 3], [4, 5], [6]];
// ❌ Цикл или рекурсия
$result = [];
foreach ($matrix as $row) {
foreach ($row as $item) {
$result[] = $item;
}
}
// ✅ Одна строка
$result = array_merge(...$matrix);
// [1, 2, 3, 4, 5, 6]
Но вот где реальная магия — когда нужно flatten + filter за раз:
$data = [[1, 0, 2], [null, 3], [false, 4, '']];
$result = array_values(
array_filter(
array_merge(...$data)
)
);
// [1, 2, 3, 4]
⚠️ Ловушки
— array_merge(...$matrix) упадёт с ошибкой на пустом массиве [].
— Работает только для одного уровня вложенности.
📦 В продакшене это спасает при обработке сгруппированных результатов из БД, когда ORM отдаёт Collection[] и нужно быстро схлопнуть в плоский список.
Библиотека пхпшника
#vardump