Библиотека PHP программиста 👨🏼‍💻👩‍💻
2.19K subscribers
315 photos
168 videos
7 files
331 links
Полезные материалы по PHP, Laravel, Symfony, CodeIgniter, CakePHP, Phalcon

По всем вопросам @evgenycarter
Download Telegram
🚀 Подпишись и прокачай свои скилы: лучшие каналы для IT-специалистов 👨‍💻📲

Папка с каналами для DevOps, Linux - Windows СисАдминов 👍

Папка с каналами для 1С программистов 🧑‍💻

Папка с каналами для C++ программистов 👩‍💻

Папка с каналами для Python программистов 👩‍💻

Папка с каналами для Java программистов 🖥

Папка с книгами для программистов 📚

Папка для программистов (frontend, backend, iOS, Android) 💻


GitHub Сообщество 🧑‍💻
https://t.me/Githublib Интересное из GitHub

Базы данных (Data Base) 🖥
https://t.me/database_info Все про базы данных


Разработка игр 📱
https://t.me/game_devv Все о разработке игр

БигДата, машинное обучение 🖥
https://t.me/bigdata_1 Data Science, Big Data, Machine Learning, Deep Learning


QA, тестирование 🖥
https://t.me/testlab_qa Библиотека тестировщика

Шутки программистов 📌
https://t.me/itumor Шутки программистов

Защита, взлом, безопасность 💻
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free

Книги, статьи для дизайнеров 🎨
https://t.me/ux_web Статьи, книги для дизайнеров

Математика 🧮
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике

Excel лайфхак🙃
https://t.me/Excel_lifehack

Технологии 🖥
https://t.me/tikon_1 Новости высоких технологий, науки и техники💡
https://t.me/mir_teh Мир технологий (Technology World)

Вакансии 💰
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
https://t.me/rabota1C_rus Вакансии для программистов 1С
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня я хочу поговорить о том, как избавиться от дублирования кода в Laravel, особенно в тех местах, где это совсем не бросается в глаза — в валидации запросов.

Проблема

У тебя есть формы на создание и обновление сущности. И в обоих случаях в контроллере или Form Request’ах ты пишешь одинаковые правила валидации, только с небольшими отличиями.

Пример:


// StorePostRequest.php
return [
'title' => 'required|string|max:255',
'content' => 'required',
];



// UpdatePostRequest.php
return [
'title' => 'sometimes|required|string|max:255',
'content' => 'sometimes|required',
];


Решение — базовый класс с общими правилами

Создай абстрактный класс с общими правилами:


abstract class BasePostRequest extends FormRequest
{
protected function commonRules(): array
{
return [
'title' => 'string|max:255',
'content' => 'string',
];
}
}


А потом в наследниках добавляй нужные модификаторы:


// StorePostRequest.php
class StorePostRequest extends BasePostRequest
{
public function rules(): array
{
return array_merge([
'title' => 'required',
'content' => 'required',
], $this->commonRules());
}
}



// UpdatePostRequest.php
class UpdatePostRequest extends BasePostRequest
{
public function rules(): array
{
return array_merge([
'title' => 'sometimes|required',
'content' => 'sometimes|required',
], $this->commonRules());
}
}


🤔 Альтернатива — кастомная Rule-комбинация

Можно пойти дальше и использовать кастомные Rule-классы, если валидация становится сложной и завязанной на бизнес-логику.


Я часто вижу дублирование в валидации, особенно в старых проектах. Убрав это, код становится чище, а изменения в правилах — в разы проще.

А ты как организуешь валидацию? Используешь Form Request или валидируешь прямо в контроллере?

👉 @php_lib
Сегодня я покажу вам простой, но мощный способ, как ускорить отладку в Laravel при работе с большим количеством логики в контроллерах и сервисах.

🔍 Ловим баги быстрее с помощью ray() от Spatie

Обычно мы используем dd() или dump() в Laravel, чтобы посмотреть, что творится с переменными. Но как только проект становится крупнее — эти методы начинают мешать, особенно когда нужно отслеживать несколько значений в разных местах.

Спасает Ray — инструмент от Spatie, который интегрируется с Laravel и выводит отладочную информацию в отдельное десктопное приложение.

Пример:


ray($user);
ray($order)->blue();
ray()->showQueries();


Ты можешь:
- выводить переменные без прерывания скрипта;
- смотреть SQL-запросы в реальном времени;
- использовать цветовые метки, чтобы различать вывод из разных участков кода.

⚙️ Установка


composer require spatie/laravel-ray --dev


И по желанию установить десктоп-приложение с сайта Spatie.

В config/ray.php можно кастомизировать поведение: включать Ray только на dev-среде, логировать только определённые запросы и т.д.

🧠 Совет от себя

Ray особенно хорошо заходит, когда работаешь в команде — ты можешь добавить временный ray()-лог, не ломая исполнение и не мешая другим.


Пробовали Ray? Или у вас есть свои инструменты для отладки — может, кастомные макросы или трейты? Делитесь в комментах 👇

👉 @php_lib
💰Вопрос безопасности в разработке становится всё более актуальным. Но как обосновать инвестиции в безопасность для бизнеса? Как оценить её финансовую сторону?

🗓Открытый вебинар 23 апреля в 20:00 мск даст ответы на самые важные вопросы. Мы расскажем, как сэкономить на долгосрочных потерях, внедряя эффективные меры безопасности с самого начала разработки.

🧑‍💻Спикер Максим Чащин — директор по информационной безопасности в ГК «Девелоника».

Вы узнаете, сколько стоит устранение уязвимостей, как принцип «shift left» влияет на итоговую производительность и как измерять эффективность мер безопасности. Это поможет вам убедить руководство инвестировать в безопасность на всех уровнях разработки.

👉Присоединяйтесь к открытому уроку и получите скидку на большое обучение «Внедрение и работа в DevSecOps»: https://vk.cc/cKVaef

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня я покажу вам, как удобно логировать в Laravel, не засоряя код и не превращая проект в болото из Log::info() на каждом шагу.

💡 Используем каналы логирования правильно

Laravel предоставляет мощную систему логирования на базе Monolog. Но часто мы ограничиваемся дефолтным логом. А зря.

Например, создаём отдельный канал для логов оплаты:


// config/logging.php
'channels' => [
'payment' => [
'driver' => 'single',
'path' => storage_path('logs/payment.log'),
'level' => 'info',
],
],


Теперь в нужном месте можно писать:


Log::channel('payment')->info('Платёж прошёл', ['user_id' => $user->id, 'amount' => $amount]);


И всё — никакой путаницы. В laravel.log остаётся только то, что важно для всего проекта, а логи оплаты — отдельно. Можно и в телеграм скидывать, если настроить webhook.

👀 Бонус: helper-функция

Чтобы писать меньше:


if (!function_exists('payment_log')) {
function payment_log($message, array $context = []) {
\Log::channel('payment')->info($message, $context);
}
}


Теперь вызываем везде просто payment_log('Платёж принят').

Пишите в комментах, какие каналы логирования вы используете и куда пишете — в файл, телегу или Sentry?

👉 @php_lib
Открытый вебинар «Почему стоит выбрать Symfony для нового проекта» в OTUS

📅 29 апреля, 20:00 МСК · онлайн · бесплатно
👤 Спикер — Михаил Каморин

Кто ведёт
• Tech Lead в Avito
• 20 + лет в разработке (10 лет B2B, 4 года B2C)
• 10 + лет на PHP, 5 лет — на Symfony
• Автор двух RAD‑движков (Laravel + Symfony), запущенных в 10 + прод‑проектах
• Выпускник ВМК МГУ, член ПК Podlodka PHP Crew

Symfony — ядро экосистемы PHP. Разберём, как фреймворк помогает запускать и поддерживать продукты с горизонтом 5 + лет.

Ключевые вопросы
• Модульность — 25 + компонентов подключаются по мере надобности
• Гибкость — DI‑контейнер переопределяет сервисы без боли
• Стабильность — LTS 3 года, минорные версии совместимы назад
• Speed‑toolkit — Symfony CLI, Flex, автоконфигурация, Profiler

Кому полезно
— Middle/Senior PHP‑разработчикам, архитекторам и тимлидам, которым нужны строгие аргументы «за» Symfony.

Формат — 60 минут концентрированной практики + Q&A без маркетинговой воды.

Участие бесплатное. Места ограничены. Регистрируйтесь.

https://vk.cc/cL1f9x

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Сегодня я покажу вам простой способ, как разрулить хардкорный баг с session_start() в PHP.

Недавно один подписчик столкнулся с ситуацией: скрипт падает с ошибкой "Cannot send session cache limiter - headers already sent". Думаю, каждый второй PHP-разработчик хотя бы раз в жизни это видел.

Разбираемся.

💥 Причина
Ошибка возникает, когда session_start() вызывается после того, как браузеру уже отправлены заголовки. В PHP это означает — где-то до session_start() был echo, пробел вне тегов <?php ?>, или даже var_dump() для отладки. Любой вывод в браузер = PHP уже отправил заголовки. А session_start() хочет их изменить — и ловим ошибку.

Как лечить
1. Ищем вывод до session_start()
- Проверь, нет ли echo, print, отладочных функций или лишних символов до вызова session_start().
- Включи буферизацию ob_start() в начале скрипта — поможет временно «глотать» вывод:

ob_start();
session_start();

Но это костыль. Лучше всё же вычистить лишний вывод.

2. Идеальная структура файла

<?php
// Никакого вывода до этого места!
session_start();

// Весь остальной код
?>


3. Ищи BOM
Иногда редакторы типа Notepad++ добавляют невидимый символ BOM в начало файла. Он тоже считается выводом. Решается сохранением файла в UTF-8 без BOM.

🛠 Мой способ отладки
Когда всё выглядит правильно, но ошибка всё равно есть:
- Создай новый чистый файл, вставь туда session_start() — если работает, значит проблема в другом коде.
- Используй headers_sent():

if (headers_sent($file, $line)) {
echo "Вывод уже начат в $file на строке $line";
}


Это сэкономило мне кучу времени при отладке старых легаси-проектов.

👉 @php_lib
⚡️Laravel — удобный PHP-фреймворк, а его возможности выходят далеко за рамки классической веб-разработки. Хотите увидеть, как он помогает автоматизировать реальные процессы?

На бесплатном вебинаре 16 апреля в 20:00 мск покажем, как с помощью Laravel и Telegram Bot API создать Telegram-бота для дистанционного полива цветов. Подключим IoT-устройства, разберём работу с MQTT и визуализируем данные через Grafana.

Вы узнаете, как использовать Laravel в IoT-сценариях, управлять устройствами через Telegram, собирать и отображать метрики, а также получите представление о возможностях Arduino на примере ESP-8266.

👉Регистрируйтесь и получите скидку на большое обучение «Framework Laravel»: https://vk.cc/cL4HRV

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 Подборка Telegram каналов для программистов

Системное администрирование, DevOps 📌

https://t.me/bash_srv Bash Советы
https://t.me/win_sysadmin Системный Администратор Windows
https://t.me/sysadmin_girl Девочка Сисадмин
https://t.me/srv_admin_linux Админские угодья
https://t.me/linux_srv Типичный Сисадмин
https://t.me/devopslib Библиотека девопса | DevOps, SRE, Sysadmin
https://t.me/linux_odmin Linux: Системный администратор
https://t.me/devops_star DevOps Star (Звезда Девопса)
https://t.me/i_linux Системный администратор
https://t.me/linuxchmod Linux
https://t.me/sys_adminos Системный Администратор
https://t.me/tipsysdmin Типичный Сисадмин (фото железа, было/стало)
https://t.me/sysadminof Книги для админов, полезные материалы
https://t.me/i_odmin Все для системного администратора
https://t.me/i_odmin_book Библиотека Системного Администратора
https://t.me/i_odmin_chat Чат системных администраторов
https://t.me/i_DevOps DevOps: Пишем о Docker, Kubernetes и др.
https://t.me/sysadminoff Новости Линукс Linux

1C разработка 📌
https://t.me/odin1C_rus Cтатьи, курсы, советы, шаблоны кода 1С
https://t.me/DevLab1C 1С:Предприятие 8
https://t.me/razrab_1C 1C Разработчик
https://t.me/buh1C_prog 1C Программист | Бухгалтерия и Учёт
https://t.me/rabota1C_rus Вакансии для программистов 1С

Программирование C++📌
https://t.me/cpp_lib Библиотека C/C++ разработчика
https://t.me/cpp_knigi Книги для программистов C/C++
https://t.me/cpp_geek Учим C/C++ на примерах

Программирование Python 📌
https://t.me/pythonofff Python академия.
https://t.me/BookPython Библиотека Python разработчика
https://t.me/python_real Python подборки на русском и английском
https://t.me/python_360 Книги по Python

Java разработка 📌
https://t.me/BookJava Библиотека Java разработчика
https://t.me/java_360 Книги по Java Rus
https://t.me/java_geek Учим Java на примерах

GitHub Сообщество 📌
https://t.me/Githublib Интересное из GitHub

Базы данных (Data Base) 📌
https://t.me/database_info Все про базы данных

Мобильная разработка: iOS, Android 📌
https://t.me/developer_mobila Мобильная разработка
https://t.me/kotlin_lib Подборки полезного материала по Kotlin

Фронтенд разработка 📌
https://t.me/frontend_1 Подборки для frontend разработчиков
https://t.me/frontend_sovet Frontend советы, примеры и практика!
https://t.me/React_lib Подборки по React js и все что с ним связано

Разработка игр 📌
https://t.me/game_devv Все о разработке игр

Библиотеки 📌
https://t.me/book_for_dev Книги для программистов Rus
https://t.me/programmist_of Книги по программированию
https://t.me/proglb Библиотека программиста
https://t.me/bfbook Книги для программистов

БигДата, машинное обучение 📌
https://t.me/bigdata_1 Big Data, Machine Learning

Программирование 📌
https://t.me/bookflow Лекции, видеоуроки, доклады с IT конференций
https://t.me/rust_lib Полезный контент по программированию на Rust
https://t.me/golang_lib Библиотека Go (Golang) разработчика
https://t.me/itmozg Программисты, дизайнеры, новости из мира IT
https://t.me/php_lib Библиотека PHP программиста 👨🏼‍💻👩‍💻
https://t.me/nodejs_lib Подборки по Node js и все что с ним связано
https://t.me/ruby_lib Библиотека Ruby программиста
https://t.me/lifeproger Жизнь программиста. Авторский канал.

QA, тестирование 📌
https://t.me/testlab_qa Библиотека тестировщика

Шутки программистов 📌
https://t.me/itumor Шутки программистов

Защита, взлом, безопасность 📌
https://t.me/thehaking Канал о кибербезопасности
https://t.me/xakep_2 Хакер Free

Книги, статьи для дизайнеров 📌
https://t.me/ux_web Статьи, книги для дизайнеров

Математика 📌
https://t.me/Pomatematike Канал по математике
https://t.me/phis_mat Обучающие видео, книги по Физике и Математике
https://t.me/matgeoru Математика | Геометрия | Логика

Excel лайфхак📌
https://t.me/Excel_lifehack

https://t.me/mir_teh Мир технологий (Technology World)

Вакансии 📌
https://t.me/sysadmin_rabota Системный Администратор
https://t.me/progjob Вакансии в IT
Сегодня я хочу показать вам простой, но очень полезный приём для работы с массивами в PHP — использование функции array_column().

Очень часто бывает задача: из многомерного массива "вытащить" только один столбец данных. Например, у вас есть массив пользователей:


$users = [
['id' => 1, 'name' => 'Иван', 'email' => 'ivan@example.com'],
['id' => 2, 'name' => 'Ольга', 'email' => 'olga@example.com'],
['id' => 3, 'name' => 'Павел', 'email' => 'pavel@example.com'],
];


И нужно получить только список всех email'ов. Многие делают это через foreach, но есть более элегантное решение:


$emails = array_column($users, 'email');


Результат будет таким:


[
'ivan@example.com',
'olga@example.com',
'pavel@example.com'
]


А ещё array_column() позволяет указать третий параметр — ключ массива. Например, сделать email по id:


$emailsById = array_column($users, 'email', 'id');


И тогда получится:


[
1 => 'ivan@example.com',
2 => 'olga@example.com',
3 => 'pavel@example.com'
]


Это удобный способ быстрого преобразования данных без лишнего кода.

Пользуетесь ли вы array_column() в своих проектах? Или предпочитаете что-то другое? Напишите в комментариях!

👉 @php_lib
Через 2 дня — бесплатный вебинар OTUS «Почему стоит выбрать Symfony для нового проекта»

🗓 29 апреля, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito

Symfony остаётся ядром экосистемы PHP. Разберём, почему фреймворк подходит для запуска и долгосрочной поддержки продуктов.

Что обсудим
• Модульность: более 25 компонентов подключаются по нужде.
• Гибкость: мощный DI‑контейнер и переопределяемые сервисы.
• Стабильность: LTS 3 года, минорные версии совместимы назад.
• Dev‑ускорители: Symfony CLI, Flex, автоконфигурация, Profiler.

Кому полезно
— PHP‑разработчикам, которые выбирают стек для нового проекта.
— Тем, кому нужны строгие аргументы «за» Symfony или PHP.

⚡️ Слотов осталось мало — регистрация закроется в день мероприятия.
🔗 Успейте записаться → https://vk.cc/cLcjA7

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня хочу рассказать вам про одну ошибку, которую я часто встречаю у начинающих PHP-разработчиков — неправильную работу с датами и временем.

Когда вы используете функции вроде date(), strtotime(), time() напрямую без явной установки временной зоны (timezone), ваш код может начать вести себя непредсказуемо. Особенно если ваш проект запущен на серверах в разных регионах.

Чтобы избежать проблем:
- Всегда задавайте временную зону явно через date_default_timezone_set('Your/Timezone'); в начале вашего приложения.
- Или лучше используйте объекты DateTime и DateTimeZone, они гораздо удобнее для работы с временными зонами и манипуляциями с датами.

Пример хорошего подхода:


$date = new DateTime('now', new DateTimeZone('Europe/Moscow'));
echo $date->format('Y-m-d H:i:s');


И еще одна рекомендация — всегда храните даты в базе данных в формате UTC, а уже при выводе преобразовывайте их в нужную временную зону для пользователя.

Небольшая дисциплина в работе с временем сэкономит вам кучу нервов в будущем. Проверено на реальных проектах!

👉 @php_lib
FastExcelWriter — избавление от проклятия PhpSpreadsheet

Наверняка каждый php-разработчик, хоть раз сталкивавшийся с чтением или записью Excel-файлов, знает про библиотеку PhpSpreadsheet (в прошлом - PHPExcel). Это мощная библиотека на чистом php, которая позволяет читать, а, главное, создавать Excel-таблицы. И все с ней хорошо, пока работаешь с небольшим набором данных. Но при работе с большими файлами PhpSpreadsheet начинает чудовищно отжирать память, да и производительность резко падает, и php-скрипт, использующий библиотеку, часто просто отваливается по таймауту. И проблема - в архитектуре библиотеки.

Библиотека PhpSpreadsheet, казалось бы, спроектирована очень правильно: листы таблицы, строки, ячейки, прочие сущности - это все классы, стили, форматы и всевозможные свойства тоже состоят из классов. И когда создается таблица, то в памяти создается огромное количество связанных между собой объектов, им задаются свойства, выполняются всевозможные манипуляции, ячейки заполняются данными, всё-всё это держится в памяти, и пишется в файл только в момент сохранения.

https://habr.com/ru/articles/904710/

👉 @php_lib
🐘 Тест по PHP

🔥 Проверь насколько хорошо ты знаешь PHP

Ответишь — пройдешь на продвинутый курс "PHP Developer. Professional" от OTUS по специальной цене.

➡️ ПРОЙТИ ТЕСТ: https://vk.cc/cLdYm8

Приятный бонус Курс можно приобрести в рассрочку и без переплаты

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Please open Telegram to view this post
VIEW IN TELEGRAM
Сегодня я покажу вам, как быстро и удобно организовать автозагрузку классов в PHP без использования Composer.

Мы все любим Composer, но бывают ситуации, когда он просто неуместен — например, в небольшом проекте, скрипте или легаси-коде, где Composer не использовался изначально. В таких случаях можно сделать свою простую, но эффективную автозагрузку.

Вот базовый пример:


spl_autoload_register(function ($class) {
$baseDir = __DIR__ . '/src/';
$classPath = str_replace('\\', '/', $class) . '.php';
$file = $baseDir . $classPath;

if (file_exists($file)) {
require $file;
}
});


Что здесь происходит:
- spl_autoload_register регистрирует анонимную функцию, которая будет вызываться при попытке использовать неизвестный класс.
- Класс App\Services\MailService превратится в путь src/App/Services/MailService.php
- Если файл существует — он подключается.

Это суперудобный способ структурировать код и избавиться от бесконечных require.

Если хочется чуть больше гибкости — можно добавить поддержку нескольких базовых директорий, логирование ошибок или даже кэширование найденных путей.

Вопрос к вам:
А вы когда-нибудь писали свою автозагрузку? Или полностью доверяете Composer?

👉 @php_lib
Сегодня я покажу вам, как безопасно работать с пользовательским вводом в PHP — тема старая, но до сих пор частая причина уязвимостей.

Часто вижу в коде что-то вроде:


$id = $_GET['id'];
$query = "SELECT * FROM users WHERE id = $id";


Если вы всё ещё так делаете — пора остановиться. Это прямое приглашение для SQL-инъекций. Даже если вы думаете "ну я же intval() применяю", это не решение.

Правильный подход — использовать подготовленные выражения (prepared statements). Пример на PDO:


$id = $_GET['id'];
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute(['id' => $id]);
$user = $stmt->fetch();


Если вы используете mysqli, там тоже есть prepare() — не игнорируйте его. Никогда не вставляйте переменные напрямую в SQL-запросы.

Также стоит помнить: фильтрация ≠ экранирование, и экранирование ≠ защита. Настоящая защита — это изоляция данных от SQL с помощью prepare().

✍️ А как вы валидируете и обрабатываете пользовательские данные? Используете ли какую-то свою обёртку или ORM? Поделитесь в комментариях.

👉 @php_lib
Открытый вебинар «Локализация текстов в Symfony» в OTUS

🗓 15 мая, 20:00 МСК · онлайн · бесплатно
👤 Спикер — Михаил Каморин, Tech Lead Avito, 5 лет на Symfony

Symfony уверенно решает задачу мультиязычности — но что, если переводы живут в БД, а не в yaml-файлах? На вебинаре разберём базовый пример, как «подружить» symfony/translation с динамическими строками — без глубокого погружения во все тонкости компонента.

Что разберём
• Стандартная локализация статических текстов: настройка, plural-формы, fallback-языки.
• Подход к динамическим переводам в БД: таблицы, базовый Doctrine-маппинг.
• Практический пример: сохраним и извлечём строки, посмотрим метрики в Profiler.

Кому полезно
— Middle/Senior PHP-разработчикам, архитекторам и тимлидам, которые строят мульти-язычные сервисы или ищут нетривиальные модели хранения.

Формат — 60 минут концентрированной практики + Q&A без воды.

🔗 Регистрация

Слоты ограничены; участие бесплатное.

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня я хочу поделиться приёмом, который сильно упростил мне жизнь при отладке в PHP.

🛠️ Как дебажить сложные объекты в Laravel удобно?

Когда ты работаешь с коллекциями, запросами или вложенными структурами, dd() или dump() часто захламляют вывод. Но есть куда более изящный способ:


logger($someObject);


Этот метод не прерывает выполнение скрипта, в отличие от dd(), и пишет в storage/logs/laravel.log. И вот тут начинается магия:

📌 Хочешь, чтобы лог был читаемым? Добавь кастомный формат:


logger()->info('User data', [$user->toArray()]);


Или ещё лучше — используй Laravel-помощники вроде tap():


tap($response, fn($res) => logger($res->toArray()));


💡 Это особенно удобно, когда ты хочешь просто взглянуть на данные, не роняя приложение.


🔥 Бонус: в .env можно задать LOG_LEVEL=debug, и ты увидишь всё, даже что делает сам Laravel под капотом.

Такие мелочи превращают обычную отладку в аккуратный контроль за происходящим в приложении.

А как ты обычно дебажишь в Laravel — через dd() или есть свои фишки?

👉 @php_lib
Сегодня я покажу вам, как элегантно избавиться от жёсткой зависимости от фреймворков в ваших PHP-проектах. Особенно это актуально, если вы работаете с Laravel, Symfony или любым другим тяжеловесом, и со временем начинаете чувствовать, что проект стал слишком «завязан» на конкретную экосистему.

💡 Проблема: вы используете, скажем, Illuminate\Http\Request, Illuminate\Support\Collection, или ContainerInterface из Laravel — и всё, вы уже внутри. Попробуйте вынести бизнес-логику в отдельный пакет — и он сразу неработоспособен вне Laravel.

🎯 Решение: разделяйте инфраструктуру и домен.
Вот несколько практических шагов:

1. Вводите интерфейсы в домене.
Вместо Illuminate\Http\Request — свой App\Contracts\RequestInterface. Это можно реализовать через адаптер или DTO.

2. Убирайте фреймворк из бизнес-логики.
Доменный код не должен знать про контроллеры, контейнеры и фасады. Он должен работать с чистыми данными, переданными через интерфейсы или value-объекты.

3. Интеграция на уровне Application Layer.
Фреймворк используется для "склейки" — он передаёт данные в домен и получает результат. Например, Laravel Controller вызывает сервис, но сервис не зависит от Laravel.

4. Проверяйте независимость.
Попробуйте запустить доменную часть проекта в консольном скрипте или тесте вне Laravel — если всё работает, вы на правильном пути.

📦 В результате вы получаете код, который легко тестировать, переносить между проектами, использовать вне фреймворка — хоть в Laravel, хоть в Symfony, хоть в чистом PHP.

✍️ Я лично начал писать всю бизнес-логику как Composer-пакеты без зависимости от Laravel. Это не просто — особенно поначалу — но это окупается на 100%.

Как вы решаете проблему зависимости от фреймворков? Поделитесь опытом 👇

👉 @php_lib
Через 2 дня — бесплатный вебинар OTUS «Локализация текстов в Symfony»

🗓 15 мая, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito

Symfony-проекты часто сталкиваются с задачей мультиязычности. Как локализовать статические строки — понятно, а что делать с динамическими текстами в БД? На вебинаре покажем базовый рабочий маппинг для обоих сценариев.

Что успеем за 60 минут
• Настроим компонент symfony/translation для статических файлов.
• Построим простую схему БД и Doctrine-маппинг для динамических переводов.
• Сохраним, извлечём и отладим строки в Profiler.
• Ответим на живые вопросы в Q&A.

Кому стоит прийти
— Middle/Senior PHP-разработчикам, архитекторам и тимлидам, которым нужны готовые паттерны локализации или нестандартные модели хранения.

⚡️ Слотов осталось мало — регистрация закроется в день мероприятия

🔗 Успейте записаться

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня расскажу про одну из самых частых болей в любом проекте на Laravel — отладку запросов с Eloquent и N+1 проблемой.

Ты наверняка сталкивался с ситуацией: всё работает, но чуть-чуть замедляется. Начинаешь копать и видишь кучу повторяющихся SQL-запросов. Это классическая N+1 проблема — когда вместо одного запроса Laravel делает десятки.

👀 Как это проявляется?

У тебя есть, например, список постов и у каждого поста автор:


$posts = Post::all();

foreach ($posts as $post) {
echo $post->user->name;
}


Laravel выполнит 1 запрос на посты и N запросов на пользователей. А должен был бы — 2 запроса максимум.

🛠 Решение простое — eager loading:


$posts = Post::with('user')->get();


Теперь Laravel сначала загрузит всех постов, а потом сразу всех юзеров одним вторым запросом.



📦 Но как быстро выявить такие ошибки?

Используй Laravel Debugbar или Clockwork. Они наглядно показывают все SQL-запросы и сразу виден N+1.

Ещё один вариант — в проде подключить Laravel Telescope, если это безопасно, или поставить простую логику, которая логирует количество SQL-запросов на каждый HTTP-запрос.


⚠️ Совет: всегда используй with() при выборке данных для списков, особенно если в шаблоне дергаешь связанные модели.

👉 @php_lib