PHP-BE1
310 subscribers
337 photos
11 videos
19 files
618 links
Канал по PHP, полезный и интересный контент для всех уровней.
По вопросам сотрудничества @cyberJohnny
Download Telegram
Выпуск СУБД MySQL 9.3.0

Компания Oracle сформировала новую ветку СУБД MySQL 9.3.0. Сборки MySQL Community Server 9.3.0 подготовлены для всех основных дистрибутивов Linux, FreeBSD, macOS и Windows. В соответствии с внедрённой в 2023 году новой моделью формирования релизов, MySQL 9.3 отнесён к веткам "Innovation". Innovation-ветки рекомендованы для тех, кто хочет раньше получать доступ к новой функциональности, публикуются каждые 3 месяца и поддерживаются только до публикации следующего значительного релиза (например, после появления ветки 9.3 прекращена поддержка ветки 9.2). Летом планируют сформировать LTS-релиз 9.4, рекомендованный для внедрений, которым необходима предсказуемость и длительное сохранение неизменного поведения. Следом за LTS-веткой будет сформирована новая Innovation-ветка - MySQL 10.0.

https://www.opennet.ru/opennews/art.shtml?num=63106

@php_be1
Открытый вебинар «Почему стоит выбрать 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://clck.ru/3LaSdQ

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
Сегодня я расскажу, как удобно осуществлять логирование в 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_be1
⚡️Уже умеете работать с PHP и хотите перейти на новый уровень? Laravel даст вам системный подход, архитектуру без хаоса и скорость, которая радует менеджеров и ревьюеров.

Обучение от OTUS — это живая работа с кодом, практикующие эксперты и фокус на бизнес-задачи, а не абстрактные “учебные примеры”. Мы не перегружаем теорией — только то, что действительно нужно в реальных проектах. Через 3 месяца вы будете уверенно использовать Laravel в проде и уметь разворачивать защищённые, протестированные приложения.

Программа обновлена под текущие требования рынка, а диплом OTUS котируется у ведущих компаний.

👉Пройдите вступительное тестирование и получите скидку на обучение: https://clck.ru/3LZZHk

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Сегодня я поделюсь с вами простым способом, как решить сложную проблему с 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_be1]
Новый фреймворк Tempest
Фреймворк, который не мешает писать код
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
Сегодня я хочу рассказать вам о простом, но очень полезном приёме для работы с массивами в 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]
ДевОпс и Laravel: Очереди и Обработчики в Продакшене
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]
Наблюдатели и Слушатели в Laravel — в чём разница?
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 без применения 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]
Сегодня расскажу, как правильно и безопасно работать с вводом пользователя в 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]
Открытый вебинар «Локализация текстов в 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 8.4.7 и 8.3.21
https://www.php.net/ChangeLog-8.php

@php_be1