Новый фреймворк Tempest
Фреймворк, который не мешает писать код
https://tempestphp.com/blog/discovery-explained
@php_be1
Фреймворк, который не мешает писать код
https://tempestphp.com/blog/discovery-explained
@php_be1
Через 2 дня — бесплатный вебинар OTUS «Почему стоит выбрать Symfony для нового проекта»
🗓 29 апреля, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito
Symfony остаётся ядром экосистемы PHP. Разберём, почему фреймворк подходит для запуска и долгосрочной поддержки продуктов.
Что обсудим
• Модульность: более 25 компонентов подключаются по нужде.
• Гибкость: мощный DI‑контейнер и переопределяемые сервисы.
• Стабильность: LTS 3 года, минорные версии совместимы назад.
• Dev‑ускорители: Symfony CLI, Flex, автоконфигурация, Profiler.
Кому полезно
— PHP‑разработчикам, которые выбирают стек для нового проекта.
— Тем, кому нужны строгие аргументы «за» Symfony или PHP.
⚡️ Слотов осталось мало — регистрация закроется в день мероприятия.
🔗 Успейте записаться → https://clck.ru/3LdKmm
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🗓 29 апреля, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito
Symfony остаётся ядром экосистемы PHP. Разберём, почему фреймворк подходит для запуска и долгосрочной поддержки продуктов.
Что обсудим
• Модульность: более 25 компонентов подключаются по нужде.
• Гибкость: мощный DI‑контейнер и переопределяемые сервисы.
• Стабильность: LTS 3 года, минорные версии совместимы назад.
• Dev‑ускорители: Symfony CLI, Flex, автоконфигурация, Profiler.
Кому полезно
— PHP‑разработчикам, которые выбирают стек для нового проекта.
— Тем, кому нужны строгие аргументы «за» Symfony или PHP.
⚡️ Слотов осталось мало — регистрация закроется в день мероприятия.
🔗 Успейте записаться → https://clck.ru/3LdKmm
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня я хочу рассказать вам о простом, но очень полезном приёме для работы с массивами в 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_be1]
Существует частая задача: из многомерного массива "извлечь" только один столбец данных. Например, у вас есть массив пользователей:
$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_be1]
ДевОпс и Laravel: Очереди и Обработчики в Продакшене
https://martinjoo.dev/laravel-queues-and-workers-in-production
@php_be1
https://martinjoo.dev/laravel-queues-and-workers-in-production
@php_be1
Сегодня я хочу поделиться с вами одной распространенной ошибкой, которую часто совершают начинающие 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_be1]
Когда вы используете такие функции, как 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_be1]
Наблюдатели и Слушатели в Laravel — в чём разница?
https://bert.gent/articles/2025-04-23/laravel-observers-vs-event-listeners-whats-the-difference
@php_be1
https://bert.gent/articles/2025-04-23/laravel-observers-vs-event-listeners-whats-the-difference
@php_be1
FastExcelWriter — решение проблемы с PhpSpreadsheet
Наверняка каждый php-разработчик, который хоть раз работал с чтением или записью Excel-файлов, знает о библиотеке PhpSpreadsheet (ранее - PHPExcel). Это мощная библиотека на чистом php, позволяющая читать и, что более важно, создавать Excel-таблицы. Всё хорошо, пока вы работаете с небольшими наборами данных. Но при работе с большими файлами PhpSpreadsheet начинает сильно потреблять память, а производительность резко падает, и php-скрипт, использующий эту библиотеку, часто просто зависает из-за превышения времени выполнения. Проблема заключается в архитектуре библиотеки.
Библиотека PhpSpreadsheet, казалось бы, спроектирована довольно грамотно: листы таблицы, строки, ячейки и другие сущности — все это классы, стили, форматы и различные свойства также представляют собой классы. Когда создается таблица, в памяти создается огромное количество взаимосвязанных объектов, им задаются свойства, выполняются различные манипуляции, ячейки заполняются данными, и всё это хранится в памяти, а запись в файл происходит только в момент сохранения.
https://habr.com/ru/articles/904710/
👉 [|@php_be1]
Наверняка каждый php-разработчик, который хоть раз работал с чтением или записью Excel-файлов, знает о библиотеке PhpSpreadsheet (ранее - PHPExcel). Это мощная библиотека на чистом php, позволяющая читать и, что более важно, создавать Excel-таблицы. Всё хорошо, пока вы работаете с небольшими наборами данных. Но при работе с большими файлами PhpSpreadsheet начинает сильно потреблять память, а производительность резко падает, и php-скрипт, использующий эту библиотеку, часто просто зависает из-за превышения времени выполнения. Проблема заключается в архитектуре библиотеки.
Библиотека PhpSpreadsheet, казалось бы, спроектирована довольно грамотно: листы таблицы, строки, ячейки и другие сущности — все это классы, стили, форматы и различные свойства также представляют собой классы. Когда создается таблица, в памяти создается огромное количество взаимосвязанных объектов, им задаются свойства, выполняются различные манипуляции, ячейки заполняются данными, и всё это хранится в памяти, а запись в файл происходит только в момент сохранения.
https://habr.com/ru/articles/904710/
👉 [|@php_be1]
Сегодня я расскажу, как быстро и удобно настроить автозагрузку классов в 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_be1]
Мы все ценим 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_be1]
Сегодня расскажу, как правильно и безопасно работать с вводом пользователя в 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_be1]
Часто встречаю в коде такой пример:
$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_be1]
Открытый вебинар «Локализация текстов в 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
🗓 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_be1]
🛠 Как удобно отлаживать сложные объекты в 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_be1]
Через 2 дня — бесплатный вебинар OTUS «Локализация текстов в Symfony»
🗓 15 мая, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito
Symfony-проекты часто сталкиваются с задачей мультиязычности. Как локализовать статические строки — понятно, а что делать с динамическими текстами в БД? На вебинаре покажем базовый рабочий маппинг для обоих сценариев.
Что успеем за 60 минут
• Настроим компонент symfony/translation для статических файлов.
• Построим простую схему БД и Doctrine-маппинг для динамических переводов.
• Сохраним, извлечём и отладим строки в Profiler.
• Ответим на живые вопросы в Q&A.
Кому стоит прийти
— Middle/Senior PHP-разработчикам, архитекторам и тимлидам, которым нужны готовые паттерны локализации или нестандартные модели хранения.
⚡️ Слотов осталось мало — регистрация закроется в день мероприятия
🔗 Успейте записаться
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🗓 15 мая, 20:00 МСК · онлайн
👤 Спикер — Михаил Каморин, Tech Lead Avito
Symfony-проекты часто сталкиваются с задачей мультиязычности. Как локализовать статические строки — понятно, а что делать с динамическими текстами в БД? На вебинаре покажем базовый рабочий маппинг для обоих сценариев.
Что успеем за 60 минут
• Настроим компонент symfony/translation для статических файлов.
• Построим простую схему БД и Doctrine-маппинг для динамических переводов.
• Сохраним, извлечём и отладим строки в Profiler.
• Ответим на живые вопросы в Q&A.
Кому стоит прийти
— Middle/Senior PHP-разработчикам, архитекторам и тимлидам, которым нужны готовые паттерны локализации или нестандартные модели хранения.
⚡️ Слотов осталось мало — регистрация закроется в день мероприятия
🔗 Успейте записаться
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня я покажу вам, как элегантно избавиться от жёсткой зависимости от фреймворков в ваших 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_be1]
💡 Проблема: вы используете, скажем, 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_be1]
Тест производительности PHP 8.4
@php_be1
https://tideways.com/profiler/blog/php-benchmarks-8-4-performance-is-steady-compared-to-8-3-and-8-2
@php_be1
https://tideways.com/profiler/blog/php-benchmarks-8-4-performance-is-steady-compared-to-8-3-and-8-2
Tideways
PHP Benchmarks: 8.4 performance is steady compared to 8.3 and 8.2
Every year, like clockwork, a new version of PHP is released at the end of November. Naturally, you want to know, how much performance gain is in this new release across common frameworks and applications? Our tests show that, in general, the performance…
Сегодня расскажу про одну из самых частых болей в любом проекте на 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_be1]
Ты наверняка сталкивался с ситуацией: всё работает, но чуть-чуть замедляется. Начинаешь копать и видишь кучу повторяющихся 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_be1]