Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter
10.5K subscribers
1.77K photos
31 videos
29 files
4.6K links
Все самое полезное для пхпшника в одном канале.

По рекламе: @tproger_sales_bot

Учиться у нас: clc.to/M561SQ

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b
Download Telegram
Forwarded from Библиотека программиста
👀 Как вы смотрите видео?

Разбираете урок, слушаете интервью фоном или начинаете на телефоне, а продолжаете на большом экране?

Хотим узнать, что делает просмотр удобным для вас. Вспомните последнее видео — ролик, урок, фильм или серию сериала — и расскажите о своём опыте. Если детали не запомнились, можно так и ответить.

🕰️ Опрос займёт около 3 минут.

В результатах сможете сравнить свои привычки с ответами других участников. А разработчики и инженеры видеоплатформы расскажут, что происходит по ту сторону экрана, пока вы смотрите видео.

🔗 Поделиться опытом

🐸 Библиотека программиста
Please open Telegram to view this post
VIEW IN TELEGRAM
Clockwork: куда ушло время PHP-запроса

Страница тормозит, а в логах только общий ответ? Clockwork собирает данные о выполнении приложения: запросы к БД, логи, события и timeline. В Laravel интеграция устанавливается через composer require itsgoingd/clockwork, собранные запросы можно смотреть на /clockwork.

Свои этапы тоже можно пометить событиями. На карточке — реальная учебная timeline: у import задана задержка, normalize преобразует одну строку. Это помогает отделить этапы, а не гадать по общему времени.

По умолчанию сбор активен в debug-режиме. Для команд и queue jobs нужны настройки. Данные диагностики могут содержать чувствительные значения, поэтому не открывайте интерфейс и метаданные всем пользователям приложения.

Документация и установка Clockwork

Библиотека пхпшника
👍4
Forwarded from Типичный программист
Общая папка для работы Claude Code и Codex

Луи-Франсуа Бушар собрал заметки, инструкции-скиллы, скрипты и итоги встреч в Obsidian. Его связка устроена так:

Папка хранит исходные материалы и решения
↓
Индекс указывает, где искать данные для задачи
↓
Claude Code планирует работу
↓
Codex выполняет задачи по его вызову

В описании этого рабочего процесса Бушар объясняет, зачем даёт агенту сведения для конкретной задачи. Начать предлагает с общей папки, короткого индекса и одного повторно используемого скилла.

#ии #инструменты
Forwarded from Типичный программист
🧑‍💻 Какие навыки помогают вам в разработке в 2026 году?

Что вы чаще используете в работе? В каких задачах помогает ИИ, а где проще справиться самостоятельно?

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

Опрос анонимный и займёт около 5 минут. Результаты опубликуем в общем большом исследовании.

👉 Пройти опрос
Лимит запросов в Symfony: где хранится запас токенов

Token bucket допускает всплеск запросов, пока есть токены, а затем пополняет запас с заданной частотой. В локальном примере запас равен двум: первые два запроса разрешены, третий отклонён. Через 1,1 секунды появился новый токен.

Но настройка лимита — только половина дела. Остаток хранится в состоянии лимитера. В Symfony по умолчанию это cache.rate_limiter: очистка кеша сбрасывает лимиты. Для нескольких процессов нужны общее хранилище и согласованный механизм блокировок, иначе параллельные запросы могут обойти ограничение.

Компонент начинает работать после запуска PHP и Symfony. Защиту от DoS нужно ставить раньше, на сервере или прокси. Учебный тест на карточке последовательный, он не проверяет распределённую конкуренцию.

Политики, хранилище и locks

Библиотека пхпшника
json_validate перед json_decode: один JSON разбирается дважды

Если данные сразу понадобятся в PHP, не нужно сначала вызывать json_validate. json_decode сам проверяет строку при разборе. С JSON_THROW_ON_ERROR невалидный JSON даст JsonException.

json_validate полезен, когда нужен только ответ «это корректный JSON?», а массив или объект создавать не нужно. Функция доступна с PHP 8.3 и в таком сценарии требует меньше памяти, чем декодирование.

В проверенном примере {"port":8080} валиден, {"port":} — нет. При декодировании первого получаем значение 8080, второго — исключение. Валидная строка null тоже проходит проверку: синтаксис JSON ещё не гарантирует нужную вам структуру данных.

Когда использовать json_validate

Библиотека пхпшника
💡 Symfony 8.2 сможет делать подписанную ссылку недействительной после смены пароля

Подпись защищает URL от подмены. Но сама по себе не мешает открыть одну ссылку несколько раз до истечения срока.

В разрабатываемом Symfony 8.2 у UriSigner появляется дополнительный аргумент $version. Он участвует в подписи, но не добавляется в URL.

Для сброса пароля версией может стать текущий хеш пароля:

$url = $uriSigner->sign(
$resetUrl,
new \DateInterval('PT30M'),
$user->getPassword(),
);

// При обработке ссылки:
$uriSigner->verify($request, $user->getPassword());


После сохранения нового пароля хеш изменится. Проверка старой ссылки с новым значением версии завершится исключением UnverifiedSignedUriException.

Важная деталь: verify() не погашает ссылку

Она остаётся действительной, пока состояние, выбранное в качестве версии, не изменилось. Поэтому нельзя считать такой механизм атомарной защитой от двух одновременных запросов: конкурентное выполнение нужно учитывать отдельно.

Возможность относится к будущему Symfony 8.2. Для текущего проекта сначала проверьте версию компонента.

🔗 Как работает версия подписанной ссылки

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
😎 Выбираешь один курс, второй получаешь бесплатно. Баг? Нет, акция!

До 31 октября в Proglib Academy можно выбрать два курса и заплатить только за один.

Например, можно совместить:

💥 ИИ для разработчиков — применение нейросетей в повседневной разработке: работа с кодом, тестирование и ревью.

💥 Разработка ИИ-агентов — архитектура агентов и создание собственных AI-решений.


Вместе курсы стоят 108 000 ₽, но по акции оба обойдутся в 59 000 ₽. Экономия — 49 000 ₽ 🔥

Интересуют Python и ИИ или алгоритмы и архитектура? Можно выбрать любые два курса из каталога.

Акция действует до 31 октября включительно ⏳

⏬ Собрать свой учебный билд
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱3👾1
🛠 Миграция Pinkary на MySQL обнаружила UUID в целочисленных столбцах

Приложение работает, тесты зелёные — пока не меняется движок базы данных.

В Pinkary первичный ключ questions.id был UUID. А поля parent_id и root_id создали через foreignId(), то есть как целочисленные столбцы:

$table->foreignId('parent_id');


Гибкая типизация SQLite позволяла хранить там строки UUID. При переходе на MySQL несоответствие стало проблемой: тип столбца должен соответствовать реальным значениям и связанному ключу.

Здесь легко сделать слишком широкий вывод. Проблема была именно в явных вызовах foreignId('parent_id') и foreignId('root_id'). Метод foreignIdFor() умеет определять UUID-тип по модели — это другой случай.

Что проверить до переезда

Запустите миграции и характерные запросы на том движке, который будет в рабочей среде. Помимо типов, могут отличаться правила группировки, сравнения строк и порядок результатов при одинаковых временных метках.

ORM делает запросы удобнее, но не делает SQLite и MySQL взаимозаменяемыми во всех деталях.

🔗 Разбор миграции от разработчика Pinkary

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
💡 EntityExists в Symfony 8.2 проверит сущность по идентификатору, но пропустит пустое значение

API получает userId. Проверить, что это строка, недостаточно: пользователь с таким идентификатором может не существовать.

В будущем Symfony 8.2 для этой задачи появится ограничение EntityExists из Doctrine Bridge:

use App\Entity\User;
use Symfony\Bridge\Doctrine\Validator\Constraints\EntityExists;
use Symfony\Component\Validator\Constraints as Assert;

final class AssignOrderCommand
{
#[Assert\NotBlank]
#[EntityExists(entityClass: User::class)]
public string $userId;
}


По умолчанию поиск идёт по идентификатору сущности. Можно выбрать другое поле через identifierField или задать собственный метод репозитория.

Зачем рядом NotBlank

EntityExists считает null и пустую строку допустимыми. Если поле обязательно, это отдельное правило.

Есть ещё две границы. Существование записи не означает, что текущему пользователю разрешено с ней работать. И успешная проверка не гарантирует, что запись не удалят до сохранения операции.

Поэтому авторизацию и ограничения целостности базы такая валидация не заменяет.

🔗 Новые ограничения валидации Symfony 8.2

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1
🛠 Laravel Cloud создаёт отдельное окружение для проверки каждого pull request

Один staging на всю команду быстро превращается в очередь: пока дизайнер смотрит одну ветку, следующую выкатывать нельзя.

В Laravel Cloud можно настроить автоматизацию, которая создаёт окружение при открытии pull request. У него будут собственный URL и отдельно созданные ресурсы. Новые коммиты обновляют развёрнутую версию, а после закрытия или слияния PR автоматическая очистка может удалить окружение и созданные для него ресурсы.

Это возможность платформы Laravel Cloud, а не функция, которая автоматически появляется в любом Laravel-приложении.

Изоляция важнее дополнительного URL

Проверять миграции и фоновые задания безопаснее с отдельными базой, кешем и тестовыми ключами интеграций. Подключённая рабочая база превращает проверку ветки в реальные изменения данных.

Для простаивающих окружений предусмотрено масштабирование до нуля там, где ресурс его поддерживает. Но это не обещание полностью бесплатного стека: хранение данных и другие ресурсы могут продолжать оплачиваться.

Полезный результат — возможность проверить весь пользовательский сценарий, не перезаписывая чужой staging.

🔗 Как устроены окружения для pull request

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
📌 Один курс — хорошее вложение в себя. Два по той же цене — ещё лучше.

В Proglib Academy действует акция: покупаешь один курс, а второй получаешь в подарок.

Например, можно совместить два направления по работе с ИИ:

💥 ИИ для разработчиков — применение нейросетей в повседневной разработке: работа с кодом, тестирование и ревью.

💥 Разработка ИИ-агентов — архитектура агентов и создание собственных AI-решений.


📍 Разница в цене — почти 50 тысяч рублей. Можно освоить больше, не выходя за рамки запланированного бюджета.

А если тебе интереснее Python, алгоритмы, backend или DevOps — выбирай другую пару курсов из каталога.

Акция действует до 31 октября включительно ⏳

⏮️ Пора прокачать свой стек
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱2
⚡️ Symfony 8.2 заранее подготовит список слушателей вместо повторной регистрации на каждом запросе

Контейнер уже знает, какие слушатели обрабатывают события. Зачем при создании диспетчера снова вызывать addListener() и создавать замыкания?

В разрабатываемом Symfony 8.2 сервис event_dispatcher использует CompiledEventDispatcher. Он получает заранее подготовленный массив идентификаторов сервисов и методов в нужном порядке. OPcache хранит массив в общей памяти, а локатор загружает слушателей по мере необходимости.

В приведённом микробенчмарке с 75 слушателями создание диспетчера сократилось с 33,7 до 0,48 микросекунды.

Это ускорение создания, а не всего приложения

Сама отправка событий работает с прежней скоростью. Слушатели по-прежнему создаются перед выполнением; если событие не отправлено или распространение остановлено, оставшиеся сервисы не создаются.

Добавление и удаление слушателей на общем event_dispatcher во время выполнения заставляет его перейти к обычному диспетчеру. В Symfony 8.2 такие вызовы помечаются устаревающими.

Перед обновлением стоит поискать addListener(), addSubscriber() и соответствующие удаления именно на общем сервисе.

🔗 Как работает скомпилированный диспетчер

🐸 Библиотека пхпшника
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4