Сегодня я покажу вам простой, но мощный способ, как ускорить отладку в Laravel при работе с большим количеством логики в контроллерах и сервисах.
🔍 Ловим баги быстрее с помощью
Обычно мы используем
Спасает Ray — инструмент от Spatie, который интегрируется с Laravel и выводит отладочную информацию в отдельное десктопное приложение.
Пример:
Ты можешь:
- выводить переменные без прерывания скрипта;
- смотреть SQL-запросы в реальном времени;
- использовать цветовые метки, чтобы различать вывод из разных участков кода.
⚙️ Установка
И по желанию установить десктоп-приложение с сайта Spatie.
В
🧠 Совет от себя
Ray особенно хорошо заходит, когда работаешь в команде — ты можешь добавить временный
Пробовали Ray? Или у вас есть свои инструменты для отладки — может, кастомные макросы или трейты? Делитесь в комментах 👇
👉 @php_lib
🔍 Ловим баги быстрее с помощью
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
👍6
Сегодня я покажу вам, как удобно логировать в Laravel, не засоряя код и не превращая проект в болото из
💡 Используем каналы логирования правильно
Laravel предоставляет мощную систему логирования на базе Monolog. Но часто мы ограничиваемся дефолтным логом. А зря.
Например, создаём отдельный канал для логов оплаты:
Теперь в нужном месте можно писать:
И всё — никакой путаницы. В
👀 Бонус: helper-функция
Чтобы писать меньше:
Теперь вызываем везде просто
Пишите в комментах, какие каналы логирования вы используете и куда пишете — в файл, телегу или Sentry?
👉 @php_lib
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
👍5
Сегодня я покажу вам простой способ, как разрулить хардкорный баг с session_start() в PHP.
Недавно один подписчик столкнулся с ситуацией: скрипт падает с ошибкой "Cannot send session cache limiter - headers already sent". Думаю, каждый второй PHP-разработчик хотя бы раз в жизни это видел.
Разбираемся.
💥 Причина
Ошибка возникает, когда
✅ Как лечить
1. Ищем вывод до session_start()
- Проверь, нет ли
- Включи буферизацию
Но это костыль. Лучше всё же вычистить лишний вывод.
2. Идеальная структура файла
3. Ищи BOM
Иногда редакторы типа Notepad++ добавляют невидимый символ BOM в начало файла. Он тоже считается выводом. Решается сохранением файла в UTF-8 без BOM.
🛠 Мой способ отладки
Когда всё выглядит правильно, но ошибка всё равно есть:
- Создай новый чистый файл, вставь туда
- Используй
Это сэкономило мне кучу времени при отладке старых легаси-проектов.
👉 @php_lib
Недавно один подписчик столкнулся с ситуацией: скрипт падает с ошибкой "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
👍7
🚀 Подборка 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
Системное администрирование, 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
Telegram
Bash Советы
🚀 Секреты и советы по Bash
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
🔹 Полезные трюки, хитрые однострочники и лайфхаки для работы в терминале.
🔹 Автоматизация, скрипты и оптимизация работы в Linux.
🔹 Стать мастером Bash легко – просто подпишись!
По всем вопросам @evgenycarter
❤1👍1
Сегодня я хочу показать вам простой, но очень полезный приём для работы с массивами в PHP — использование функции
Очень часто бывает задача: из многомерного массива "вытащить" только один столбец данных. Например, у вас есть массив пользователей:
И нужно получить только список всех email'ов. Многие делают это через
Результат будет таким:
А ещё
И тогда получится:
Это удобный способ быстрого преобразования данных без лишнего кода.
Пользуетесь ли вы
👉 @php_lib
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
👍18🔥2🤔1
Сегодня хочу рассказать вам про одну ошибку, которую я часто встречаю у начинающих PHP-разработчиков — неправильную работу с датами и временем.
Когда вы используете функции вроде
Чтобы избежать проблем:
- Всегда задавайте временную зону явно через
- Или лучше используйте объекты
Пример хорошего подхода:
И еще одна рекомендация — всегда храните даты в базе данных в формате UTC, а уже при выводе преобразовывайте их в нужную временную зону для пользователя.
Небольшая дисциплина в работе с временем сэкономит вам кучу нервов в будущем. Проверено на реальных проектах!
👉 @php_lib
Когда вы используете функции вроде
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
👍5🔥3💯1
FastExcelWriter — избавление от проклятия PhpSpreadsheet
Наверняка каждый php-разработчик, хоть раз сталкивавшийся с чтением или записью Excel-файлов, знает про библиотеку PhpSpreadsheet (в прошлом - PHPExcel). Это мощная библиотека на чистом php, которая позволяет читать, а, главное, создавать Excel-таблицы. И все с ней хорошо, пока работаешь с небольшим набором данных. Но при работе с большими файлами PhpSpreadsheet начинает чудовищно отжирать память, да и производительность резко падает, и php-скрипт, использующий библиотеку, часто просто отваливается по таймауту. И проблема - в архитектуре библиотеки.
Библиотека PhpSpreadsheet, казалось бы, спроектирована очень правильно: листы таблицы, строки, ячейки, прочие сущности - это все классы, стили, форматы и всевозможные свойства тоже состоят из классов. И когда создается таблица, то в памяти создается огромное количество связанных между собой объектов, им задаются свойства, выполняются всевозможные манипуляции, ячейки заполняются данными, всё-всё это держится в памяти, и пишется в файл только в момент сохранения.
https://habr.com/ru/articles/904710/
👉 @php_lib
Наверняка каждый php-разработчик, хоть раз сталкивавшийся с чтением или записью Excel-файлов, знает про библиотеку PhpSpreadsheet (в прошлом - PHPExcel). Это мощная библиотека на чистом php, которая позволяет читать, а, главное, создавать Excel-таблицы. И все с ней хорошо, пока работаешь с небольшим набором данных. Но при работе с большими файлами PhpSpreadsheet начинает чудовищно отжирать память, да и производительность резко падает, и php-скрипт, использующий библиотеку, часто просто отваливается по таймауту. И проблема - в архитектуре библиотеки.
Библиотека PhpSpreadsheet, казалось бы, спроектирована очень правильно: листы таблицы, строки, ячейки, прочие сущности - это все классы, стили, форматы и всевозможные свойства тоже состоят из классов. И когда создается таблица, то в памяти создается огромное количество связанных между собой объектов, им задаются свойства, выполняются всевозможные манипуляции, ячейки заполняются данными, всё-всё это держится в памяти, и пишется в файл только в момент сохранения.
https://habr.com/ru/articles/904710/
👉 @php_lib
👍8
Сегодня я покажу вам, как быстро и удобно организовать автозагрузку классов в PHP без использования Composer.
Мы все любим Composer, но бывают ситуации, когда он просто неуместен — например, в небольшом проекте, скрипте или легаси-коде, где Composer не использовался изначально. В таких случаях можно сделать свою простую, но эффективную автозагрузку.
Вот базовый пример:
Что здесь происходит:
-
- Класс
- Если файл существует — он подключается.
Это суперудобный способ структурировать код и избавиться от бесконечных
Если хочется чуть больше гибкости — можно добавить поддержку нескольких базовых директорий, логирование ошибок или даже кэширование найденных путей.
Вопрос к вам:
А вы когда-нибудь писали свою автозагрузку? Или полностью доверяете Composer?
👉 @php_lib
Мы все любим 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
👍6🌚1
Сегодня я покажу вам, как безопасно работать с пользовательским вводом в PHP — тема старая, но до сих пор частая причина уязвимостей.
Часто вижу в коде что-то вроде:
Если вы всё ещё так делаете — пора остановиться. Это прямое приглашение для SQL-инъекций. Даже если вы думаете "ну я же intval() применяю", это не решение.
Правильный подход — использовать подготовленные выражения (prepared statements). Пример на PDO:
Если вы используете
Также стоит помнить: фильтрация ≠ экранирование, и экранирование ≠ защита. Настоящая защита — это изоляция данных от SQL с помощью
✍️ А как вы валидируете и обрабатываете пользовательские данные? Используете ли какую-то свою обёртку или ORM? Поделитесь в комментариях.
👉 @php_lib
Часто вижу в коде что-то вроде:
$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
👍4
Сегодня я хочу поделиться приёмом, который сильно упростил мне жизнь при отладке в PHP.
🛠️ Как дебажить сложные объекты в Laravel удобно?
Когда ты работаешь с коллекциями, запросами или вложенными структурами,
Этот метод не прерывает выполнение скрипта, в отличие от
📌 Хочешь, чтобы лог был читаемым? Добавь кастомный формат:
Или ещё лучше — используй Laravel-помощники вроде
💡 Это особенно удобно, когда ты хочешь просто взглянуть на данные, не роняя приложение.
🔥 Бонус: в
Такие мелочи превращают обычную отладку в аккуратный контроль за происходящим в приложении.
А как ты обычно дебажишь в Laravel — через
👉 @php_lib
🛠️ Как дебажить сложные объекты в 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
👍6
Сегодня я покажу вам, как элегантно избавиться от жёсткой зависимости от фреймворков в ваших PHP-проектах. Особенно это актуально, если вы работаете с Laravel, Symfony или любым другим тяжеловесом, и со временем начинаете чувствовать, что проект стал слишком «завязан» на конкретную экосистему.
💡 Проблема: вы используете, скажем,
🎯 Решение: разделяйте инфраструктуру и домен.
Вот несколько практических шагов:
1. Вводите интерфейсы в домене.
Вместо
2. Убирайте фреймворк из бизнес-логики.
Доменный код не должен знать про контроллеры, контейнеры и фасады. Он должен работать с чистыми данными, переданными через интерфейсы или value-объекты.
3. Интеграция на уровне Application Layer.
Фреймворк используется для "склейки" — он передаёт данные в домен и получает результат. Например, Laravel Controller вызывает сервис, но сервис не зависит от Laravel.
4. Проверяйте независимость.
Попробуйте запустить доменную часть проекта в консольном скрипте или тесте вне Laravel — если всё работает, вы на правильном пути.
📦 В результате вы получаете код, который легко тестировать, переносить между проектами, использовать вне фреймворка — хоть в Laravel, хоть в Symfony, хоть в чистом PHP.
✍️ Я лично начал писать всю бизнес-логику как Composer-пакеты без зависимости от Laravel. Это не просто — особенно поначалу — но это окупается на 100%.
Как вы решаете проблему зависимости от фреймворков? Поделитесь опытом 👇
👉 @php_lib
💡 Проблема: вы используете, скажем,
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
👍5🤔2💩1
Сегодня расскажу про одну из самых частых болей в любом проекте на Laravel — отладку запросов с Eloquent и N+1 проблемой.
Ты наверняка сталкивался с ситуацией: всё работает, но чуть-чуть замедляется. Начинаешь копать и видишь кучу повторяющихся SQL-запросов. Это классическая N+1 проблема — когда вместо одного запроса Laravel делает десятки.
👀 Как это проявляется?
У тебя есть, например, список постов и у каждого поста автор:
Laravel выполнит 1 запрос на посты и N запросов на пользователей. А должен был бы — 2 запроса максимум.
🛠 Решение простое — eager loading:
Теперь Laravel сначала загрузит всех постов, а потом сразу всех юзеров одним вторым запросом.
📦 Но как быстро выявить такие ошибки?
Используй Laravel Debugbar или Clockwork. Они наглядно показывают все SQL-запросы и сразу виден N+1.
Ещё один вариант — в проде подключить Laravel Telescope, если это безопасно, или поставить простую логику, которая логирует количество SQL-запросов на каждый HTTP-запрос.
⚠️ Совет: всегда используй
👉 @php_lib
Ты наверняка сталкивался с ситуацией: всё работает, но чуть-чуть замедляется. Начинаешь копать и видишь кучу повторяющихся 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
👍5
Сегодня я расскажу вам о том, как настроить эффективное логирование ошибок в PHP-приложениях с помощью библиотеки Monolog.
В повседневной разработке критично не упустить важные ошибки и события, но при этом не завалить логи мусором. Monolog позволяет:
1. Группировать логи по каналам
Вы можете создавать каналы для разных частей приложения:
2. Использовать разные обработчики (handlers)
Отправка ошибок в файлы, на почту или в Slack:
3. Добавлять процессоры (processors)
Автоматически дополнять каждый лог юзер-агентом, IP и временем выполнения:
4. Форматировать вывод
Пример простого форматера:
🎯 Совет на практике: заведите отдельные файлы логов под разные уровни важности (INFO, WARNING, ERROR), чтобы при поиске нужных записей достаточно было открыть один файл.
❓ А как вы организуете логи в своих проектах? Делитесь опытом в комментариях!
👉 @php_lib
В повседневной разработке критично не упустить важные ошибки и события, но при этом не завалить логи мусором. Monolog позволяет:
1. Группировать логи по каналам
Вы можете создавать каналы для разных частей приложения:
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$dbLogger = new Logger('database');
$dbLogger->pushHandler(new StreamHandler(__DIR__.'/logs/db.log', Logger::WARNING));
2. Использовать разные обработчики (handlers)
Отправка ошибок в файлы, на почту или в Slack:
use Monolog\Handler\NativeMailerHandler;
$emailHandler = new NativeMailerHandler('you@domain.com', 'DB Error', 'app@domain.com', Logger::ERROR);
$dbLogger->pushHandler($emailHandler);
3. Добавлять процессоры (processors)
Автоматически дополнять каждый лог юзер-агентом, IP и временем выполнения:
use Monolog\Processor\WebProcessor;
$dbLogger->pushProcessor(new WebProcessor());
4. Форматировать вывод
Пример простого форматера:
use Monolog\Formatter\LineFormatter;
$formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context%\n");
$handler->setFormatter($formatter);
🎯 Совет на практике: заведите отдельные файлы логов под разные уровни важности (INFO, WARNING, ERROR), чтобы при поиске нужных записей достаточно было открыть один файл.
❓ А как вы организуете логи в своих проектах? Делитесь опытом в комментариях!
👉 @php_lib
👍5❤1👎1
Сегодня расскажу вам про одну простую, но очень полезную привычку для любого PHP-разработчика — вести чек-листы по задачам прямо в коде.
Когда проект становится чуть больше "визитки", начинают скапливаться мелкие задачи: что-то подправить, где-то доделать, что-то не забыть протестировать. В итоге куча мыслей крутится в голове, а шанс что-то упустить растёт. Как я с этим борюсь?
Я просто добавляю короткие TODO-комментарии в нужных местах кода. Например:
Каждый раз перед коммитом быстро пробегаюсь по проекту поиском по "TODO" — и вижу все свои маленькие хвосты. А когда задач становится много, использую расширения для IDE (например, "TODO Highlight" в VSCode) — и визуально сразу видно все невыполненные задачи.
Почему это работает:
* Не надо держать всё в голове.
* Любой разработчик быстро вникает в текущие проблемы кода.
* Легче планировать рефакторинг.
* Сложно забыть про важную доработку.
Советую прямо сегодня попробовать добавить пару своих TODO в код. Дай знать, пользуешься ли ты таким приёмом или предпочитаешь другие методы? Пиши в комментариях!
👉 @php_lib
Когда проект становится чуть больше "визитки", начинают скапливаться мелкие задачи: что-то подправить, где-то доделать, что-то не забыть протестировать. В итоге куча мыслей крутится в голове, а шанс что-то упустить растёт. Как я с этим борюсь?
Я просто добавляю короткие TODO-комментарии в нужных местах кода. Например:
// TODO: Проверить валидацию email после изменений
// TODO: Перевести этот блок на отдельный сервис
Каждый раз перед коммитом быстро пробегаюсь по проекту поиском по "TODO" — и вижу все свои маленькие хвосты. А когда задач становится много, использую расширения для IDE (например, "TODO Highlight" в VSCode) — и визуально сразу видно все невыполненные задачи.
Почему это работает:
* Не надо держать всё в голове.
* Любой разработчик быстро вникает в текущие проблемы кода.
* Легче планировать рефакторинг.
* Сложно забыть про важную доработку.
Советую прямо сегодня попробовать добавить пару своих TODO в код. Дай знать, пользуешься ли ты таким приёмом или предпочитаешь другие методы? Пиши в комментариях!
👉 @php_lib
👍7🙈2🌚1
💡Совет по Laravel
Знаешь ли ты, что можно выбрасывать исключения условно всего в одну строку с помощью throw_if() — идеально для лаконичного кода в контроллерах и сервисах.
👉 @php_lib
Знаешь ли ты, что можно выбрасывать исключения условно всего в одну строку с помощью throw_if() — идеально для лаконичного кода в контроллерах и сервисах.
👉 @php_lib
👍7🥴3🔥1
💡Совет по Laravel
Строишь URL с динамическими параметрами для HTTP-запроса?
Не нужно вручную склеивать длинную строку!
Используй URI-шаблоны с методом
https://laravel.com/docs/12.x/http-client#uri-templates
👉 @php_lib
Строишь URL с динамическими параметрами для HTTP-запроса?
Не нужно вручную склеивать длинную строку!
Используй URI-шаблоны с методом
withUrlParameters() — так код станет чище и понятнее при работе с API.https://laravel.com/docs/12.x/http-client#uri-templates
👉 @php_lib
👍5
strlen() vs mb_strlen(): Почему 71% PHP-разработчиков ошибаются
В этой статье разберем, как PHP работает со строками и почему даже простой вызов
https://habr.com/ru/articles/919192/
👉 @php_lib
В этой статье разберем, как PHP работает со строками и почему даже простой вызов
strlen() может привести к неожиданным результатам. На примере крайне простой задачи "что выведет echo strlen('привет!');" посмотрим, что и как влияет на подсчет длины строки, заглянем внутрь реализации strlen() и развенчаем миф о строках как массивах.https://habr.com/ru/articles/919192/
👉 @php_lib
👍4
Сегодня я покажу вам, как быстро разрулить хаос в проекте с кастомным фреймворком, где нет нормального логирования.
Ситуация: клиент дал старый проект, ошибок — куча, но логов нет вообще. В коде
Вот мой быстрый чеклист, который спасал не раз:
1. Глобальный обработчик ошибок и исключений
Добавил в
2. Простой логгер на каждый чих
Создал файл
В нужных местах пишу
3. Прокинул заголовки и запросы
В самых первых строках запроса:
Теперь видно, с чем именно клиент ломает мой старый код.
Не всегда есть время подтягивать Monolog и делать всё красиво. Иногда нужно быстро найти, где горит — и потушить. А уже потом наводить красоту.
А вы как действуете в таких ситуациях? Есть свои приёмы?
👉 @php_lib
Ситуация: клиент дал старый проект, ошибок — куча, но логов нет вообще. В коде
try-catch, а в catch — пусто. Что делать?Вот мой быстрый чеклист, который спасал не раз:
1. Глобальный обработчик ошибок и исключений
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
error_log("[PHP ERROR] $errstr in $errfile:$errline");
return false;
});
set_exception_handler(function (Throwable $e) {
error_log("[UNCAUGHT EXCEPTION] " . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
});
Добавил в
index.php, и уже вижу, что именно валится.2. Простой логгер на каждый чих
Создал файл
logger.php:
function log_debug($msg) {
file_put_contents(__DIR__.'/debug.log', date('[Y-m-d H:i:s] ') . $msg . PHP_EOL, FILE_APPEND);
}
В нужных местах пишу
log_debug('что-то случилось');. Дёшево и сердито, зато работает.3. Прокинул заголовки и запросы
В самых первых строках запроса:
log_debug("REQUEST: " . $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI']);
log_debug("HEADERS: " . json_encode(getallheaders()));
log_debug("POST: " . json_encode($_POST));
Теперь видно, с чем именно клиент ломает мой старый код.
Не всегда есть время подтягивать Monolog и делать всё красиво. Иногда нужно быстро найти, где горит — и потушить. А уже потом наводить красоту.
А вы как действуете в таких ситуациях? Есть свои приёмы?
👉 @php_lib
👍11😁1💯1
Laravel lazy() против get()
Знаешь ли ты… что можно обрабатывать большие объёмы данных из базы с помощью lazy() — это гораздо эффективнее по памяти, чем get().
👉 @php_lib
Знаешь ли ты… что можно обрабатывать большие объёмы данных из базы с помощью lazy() — это гораздо эффективнее по памяти, чем get().
👉 @php_lib
👍6❤1