en
Feedback
PHP-BE1

PHP-BE1

Open in Telegram

Канал по PHP, полезный и интересный контент для всех уровней. По вопросам сотрудничества @cyberJohnny

Show more
292
Subscribers
No data24 hours
-17 days
-330 days
Posts Archive
Сегодня я расскажу вам о том, как настроить эффективное логирование ошибок в PHP-приложениях с помощью библиотеки Monolog. В повседневной разработке критично не упустить важные ошибки и события, но при этом не завалить логи мусором. 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_be1]

Обработка ошибок транзакций в Laravel 12.9 https://www.harrisrafto.eu/elegant-transaction-error-handling-in-laravel/ @php_be1
Обработка ошибок транзакций в Laravel 12.9 https://www.harrisrafto.eu/elegant-transaction-error-handling-in-laravel/ @php_be1

Новый оператор конвейера в PHP 8.5 https://www.amitmerchant.com/the-pipe-operator-php-85/ @php_be1
Новый оператор конвейера в PHP 8.5 https://www.amitmerchant.com/the-pipe-operator-php-85/ @php_be1

Глобализируйте ограничения параметров маршрутов @php_be1
Глобализируйте ограничения параметров маршрутов @php_be1

Сегодня расскажу про одну из самых частых болей в любом проекте на 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]

А вы знали, что можно задать дефолтные значения полей БД не только в миграциях, но и в Eloquent-модели с помощью $attributes?
А вы знали, что можно задать дефолтные значения полей БД не только в миграциях, но и в Eloquent-модели с помощью $attributes? @php_be1

Сегодня я покажу вам, как элегантно избавиться от жёсткой зависимости от фреймворков в ваших 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]

Через 2 дня — бесплатный вебинар OTUS «Локализация текстов в Symfony» 🗓 15 мая, 20:00 МСК · онлайн 👤 Спикер — Михаил Камори
Через 2 дня — бесплатный вебинар OTUS «Локализация текстов в Symfony» 🗓 15 мая, 20:00 МСК · онлайн 👤 Спикер — Михаил Каморин, Tech Lead Avito Symfony-проекты часто сталкиваются с задачей мультиязычности. Как локализовать статические строки — понятно, а что делать с динамическими текстами в БД? На вебинаре покажем базовый рабочий маппинг для обоих сценариев. Что успеем за 60 минут • Настроим компонент symfony/translation для статических файлов. • Построим простую схему БД и Doctrine-маппинг для динамических переводов. • Сохраним, извлечём и отладим строки в Profiler. • Ответим на живые вопросы в Q&A. Кому стоит прийти — Middle/Senior PHP-разработчикам, архитекторам и тимлидам, которым нужны готовые паттерны локализации или нестандартные модели хранения. ⚡️ Слотов осталось мало — регистрация закроется в день мероприятия 🔗 Успейте записаться Реклама. ООО «Отус онлайн-образование», ОГРН 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]

Релиз PHP 8.4.7 и 8.3.21 https://www.php.net/ChangeLog-8.php @php_be1
Релиз PHP 8.4.7 и 8.3.21 https://www.php.net/ChangeLog-8.php @php_be1

Открытый вебинар «Локализация текстов в Symfony» в OTUS 🗓 15 мая, 20:00 МСК · онлайн · бесплатно 👤 Спикер — Михаил Каморин,
Открытый вебинар «Локализация текстов в 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 — эта тема давно известна, но всё ещё часто становится причиной уязвимостей. Часто встречаю в коде такой пример: $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]

Сегодня я расскажу, как быстро и удобно настроить автозагрузку классов в 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]

FastExcelWriter — решение проблемы с PhpSpreadsheet Наверняка каждый php-разработчик, который хоть раз работал с чтением или записью Excel-файлов, знает о библиотеке PhpSpreadsheet (ранее - PHPExcel). Это мощная библиотека на чистом php, позволяющая читать и, что более важно, создавать Excel-таблицы. Всё хорошо, пока вы работаете с небольшими наборами данных. Но при работе с большими файлами PhpSpreadsheet начинает сильно потреблять память, а производительность резко падает, и php-скрипт, использующий эту библиотеку, часто просто зависает из-за превышения времени выполнения. Проблема заключается в архитектуре библиотеки. Библиотека PhpSpreadsheet, казалось бы, спроектирована довольно грамотно: листы таблицы, строки, ячейки и другие сущности — все это классы, стили, форматы и различные свойства также представляют собой классы. Когда создается таблица, в памяти создается огромное количество взаимосвязанных объектов, им задаются свойства, выполняются различные манипуляции, ячейки заполняются данными, и всё это хранится в памяти, а запись в файл происходит только в момент сохранения. https://habr.com/ru/articles/904710/ 👉 [|@php_be1]