fa
Feedback
Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

رفتن به کانال در Telegram

Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b

نمایش بیشتر

📈 تحلیل کانال تلگرام Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter

کانال Библиотека пхпшника | PHP, Laravel, Symfony, CodeIgniter (@phpproglib) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 10 715 مشترک است و جایگاه 11 587 را در دسته فناوری و برنامه‌ها و رتبه 61 323 را در منطقه روسيا دارد.

📊 شاخص‌های مخاطب و پویایی

از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 10 715 مشترک جذب کرده است.

بر اساس آخرین داده‌ها در تاریخ 03 ژوئن, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -34 و در ۲۴ ساعت گذشته برابر 1 بوده و همچنان دسترسی گسترده‌ای حفظ شده است.

  • وضعیت تأیید: تأیید نشده
  • نرخ تعامل (ER): میانگین تعامل مخاطب 15.59% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 8.81% واکنش نسبت به کل مشترکان کسب می‌کند.
  • دسترسی پست‌ها: هر پست به طور میانگین 1 671 بازدید دریافت می‌کند. در اولین روز معمولاً 944 بازدید جمع‌آوری می‌شود.
  • واکنش‌ها و تعامل: مخاطبان به‌طور فعال حمایت می‌کنند؛ میانگین واکنش به هر پست 10 است.
  • علایق موضوعی: محتوا بر موضوعات کلیدی مانند php, laravel, пхпшника, artisan, api تمرکز دارد.

📝 توضیح و سیاست محتوایی

نویسنده این فضا را محل بیان دیدگاه‌های شخصی توصیف می‌کند:
Все самое полезное для пхпшника в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/bca892d6 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a5d13cd6fa92100ee6f68b

به لطف به‌روزرسانی‌های پرتکرار (آخرین داده در تاریخ 04 ژوئن, 2026)، کانال همواره به‌روز و دارای دسترسی بالاست. تحلیل‌ها نشان می‌دهد مخاطبان به‌طور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامه‌ها تبدیل کرده‌اند.

10 715
مشترکین
+124 ساعت
-107 روز
-3430 روز
آرشیو پست ها
⚡️ Как настроить OPcache Preloading в PHP 8.3 и не положить прод Прелоадинг компилирует классы один раз при старте FPM и держит их в shared memory. Минус ~30% к latency на каждый реквест. Но 90% настраивают его неправильно. 1️⃣ Включаем в php.ini ini
opcache.enable=1
opcache.preload=/var/www/app/preload.php
opcache.preload_user=www-data
opcache.memory_consumption=256
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
validate_timestamps=0 — на проде файлы не меняются между деплоями. Не тратим syscall на stat() каждого файла. Сброс кэша — через рестарт FPM (Deployer сделает сам). 2️⃣ Пишем preload.php правильно Наивный подход — загрузить всё подряд. Получите fatal при старте FPM. php
// ❌ так делать нельзя
$files = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator('/var/www/app/vendor')
);
foreach ($files as $file) {
    if ($file->getExtension() === 'php') {
        opcache_compile_file($file->getRealPath());
    }
}
Проблема: интерфейсы, трейты, абстрактные классы — порядок загрузки важен. Одна битая зависимость = FPM не стартует. php
// ✅ через Composer class map + мягкий fallback
// preload.php
require __DIR__ . '/vendor/autoload.php';

$classMap = require __DIR__ . '/vendor/composer/autoload_classmap.php';

$ignore = [
    '/Tests/', '/test/', '/fixtures/', '/stub/',
    '/migrations/', '/seeders/', '/factories/',
];

foreach ($classMap as $class => $file) {
    foreach ($ignore as $pattern) {
        if (str_contains($file, $pattern)) continue 2;
    }

    try {
        if (!class_exists($class, false)
            && !interface_exists($class, false)
            && !trait_exists($class, false)
            && !enum_exists($class, false)
        ) {
            require_once $file;
        }
    } catch (\Throwable) {
        // класс не загрузился — пропускаем, не роняем FPM
    }
}
class_exists($class, false)false отключает автолоад. Проверяем, не загружен ли класс уже по цепочке зависимостей. 3️⃣ Для Laravel — берём готовое bash
composer require laragear/preload
php artisan preload:generate
Пакет анализирует opcache_get_status() на работающем приложении и генерирует preload-список из реально используемых классов. Не из всего vendor. php
// config/preload.php
return [
    'condition' => true,
    'memory_limit' => 64, // MB под прелоад
    'include' => [],
    'exclude' => [
        'Illuminate\Support\Facades\*',
    ],
    'overwrite' => true,
];
Фасады исключаем — они резолвятся лениво через контейнер, прелоад им мешает. 4️⃣ Проверяем, что всё работает php
// диагностика из CLI не работает, только через FPM
// создаём роут или скрипт

$status = opcache_get_status();
$preload = $status['preload_statistics'] ?? [];

echo "Preloaded classes: " . count($preload['classes'] ?? []) . PHP_EOL;
echo "Preloaded funcs:   " . count($preload['functions'] ?? []) . PHP_EOL;
echo "Memory used:       " . round($preload['memory_consumption'] / 1024 / 1024, 2) . " MB" . PHP_EOL;
Важно: php -r "opcache_get_status();" в CLI покажет пустоту. Прелоад живёт только в памяти FPM-мастера. 5️⃣ Интегрируем в деплой php
// deploy.php (Deployer)
task('php-fpm:reload', function () {
    run('sudo systemctl reload php8.3-fpm');
});

after('deploy:symlink', 'php-fpm:reload');
reload, не restart. Reload делает graceful: мастер-процесс перечитывает конфиг и прелоад, старые воркеры дорабатывают текущие реквесты. Zero downtime. 6️⃣ Подводные камниПамять: прелоад жрёт shared memory. 2000 классов ≈ 30–50 MB. Если memory_consumption мал — часть классов молча не загрузится — Наследование: если прелоадите дочерний класс, родитель должен быть загружен раньше. Composer classmap решает это, ручной glob — нет — Enum + PHP 8.1+: backed enum'ы с интерфейсами иногда падают при прелоаде. Если ловите segfault при старте FPM — исключайте enum'ы и обновляйтесь — Xdebug: прелоад несовместим с xdebug. На dev-окружении выключайте opcache.preload

🛠 Реактивный SPA на Symfony без единой строчки React Согласись, что неприятен JS-налог: дублирование роутинга, валидации и моделей на фронте, возня с Vite и раздутые бандлы. Hotwire переворачивает схему — сервер шлёт готовые куски HTML, Turbo подменяет DOM, страница не перезагружается. 🚀 Стек первой части туториала: — фреймворк Symfony 7.4 + AssetMapper (без Webpack и Node); — компоненты Turbo Drive/Frames/Streams для бесшовных обновлений; — библиотека Stimulus там, где реально нужен JS (drag & drop); — протокол Mercure через SSE вместо возни с WebSockets на PHP; — стили Tailwind через symfonycasts-бандл (снова без npm); Крутой приём → колонки доски генерятся из PHP Enum:
enum TaskStatus: string
{
    case TODO = 'todo';
    case IN_PROGRESS = 'in_progress';
    case DONE = 'done';
}

#[ORM\Column(length: 50, enumType: TaskStatus::class)]
private TaskStatus $status = TaskStatus::TODO;
Достаточно передать TaskStatus::cases() в Twig и новый статус добавится одной строкой в Enum. Никакой правки шаблонов и магических строк (Doctrine сам сериализует значения в varchar). Во второй части туториала будет немного нативного HTML5 DnD и Turbo Streams через Mercure для синхронизации между вкладками. 🔗 Подробнее Библиотека пхпшника

Сохраняйте шпаргалку по паттернам проектирования

До 31 мая можно забрать любой курс Proglib Academy со скидкой 40% Если давно хотели прокачаться в Python, ML, алгоритмах или
До 31 мая можно забрать любой курс Proglib Academy со скидкой 40% Если давно хотели прокачаться в Python, ML, алгоритмах или AI-агентах, сейчас самое время выбрать программу и начать обучение по сниженной цене. 🎁 Разработка AI-агентов от 49.000 ₽ (вместо 69.000 ₽) Практический курс по разработке AI-агентов для автоматизации задач, работы и собственных проектов 🎁 Курс AgentOps129.000 ₽ (вместо 149.000 ₽) Для разработчиков и LLM-инженеров, которые хотят внедрять AI-логику в бэкенд и сохранять стабильность сервиса. 🎁 Математика для разработки AI-моделей 23.990 ₽ (вместо 31.990 ₽) Практическая база по математике для анализа данных, ML и дальнейшего развития в AI. 🎁 Математика для Data Scienceот 29.990 ₽ (вместо 39.990 ₽) Курс для тех, кто хочет решать задачи, которые дают на собеседованиях на позицию дата-сайентиста в бигтехе. 🎁 ML для старта в Data Science28.990 ₽ (вместо 38.990 ₽) Разберётесь в машинном обучении: от базовых понятий и линейных моделей до ансамблей, бустинга и рекомендательных систем. 🎁 Основы IT для непрограммистов16.990 ₽ (вместо 28.990 ₽) Курс для IT-рекрутеров, маркетологов, проджектов, продактов и всех, кто работает с IT, но не пишет код. 🎁 Архитектуры и шаблоны проектирования27.990 ₽ (вместо 37.900 ₽) Освоите основные паттерны проектирования и прокачаете навыки архитектора программного обеспечения. 🎁 Специалист по ИИ89.000 ₽ (вместо 113.900 ₽) Курс для тех, кто хочет получить профессию в сфере ИИ, собрать портфолио из 5 проектов и научиться разрабатывать сложных AI-агентов. 🎁 Алгоритмы и структуры данных 33.990 ₽ (вместо 57.990 ₽) Подготовитесь к алгоритмическим собеседованиям, разберёте структуры данных и научитесь писать более эффективный код. 🎁 Программирование на языке Python27.990 ₽ (вместо 47.390 ₽) Освоите Python на практике: без сухой теории, с пошаговой прокачкой навыков и итоговым проектом в портфолио. 🙌 Выбирайте курс по ссылке, оставляйте заявку, и менеджер поможет подобрать программу под ваши цели — https://clc.to/HglYew

🔧 Работаем с kubectl Нужно быстро форварднуть порт сервиса из Kubernetes на localhost для отладки? kubectl port-forward — ваш туннель в кластер без Ingress, LoadBalancer и VPN. 🔹 Зачем это нужно — Доступ к сервисам внутри кластера без внешнего endpoint-а. — Подключение к БД, Redis, RabbitMQ для отладки прямо с рабочей машины. — Не нужно менять конфиги, создавать NodePort или разворачивать Ingress. 🔹 Как использовать — К поду: kubectl port-forward pod/my-pod 8080:80 — К сервису: kubectl port-forward svc/my-service 5432:5432 — К деплойменту: kubectl port-forward deploy/my-app 3000:3000 — Другой локальный порт: kubectl port-forward svc/postgres 15432:5432 (localhost:15432 → postgres:5432) — Слушать на всех интерфейсах: kubectl port-forward --address 0.0.0.0 svc/my-service 8080:80

💥 «Clean Code» — самая переоценённая книга в индустрии Я не говорю, что книга плохая. Я говорю, что она принесла массовому разработчику больше вреда, чем пользы. Uncle Bob написал набор рекомендаций, а индустрия превратила их в религию. «Метод не длиннее 5 строк». «Каждый класс — одна ответственность». «Имя должно быть самодокументирующим». Звучит красиво, а на практике: — 47 приватных методов, каждый вызывается ровно один раз — AbstractNotificationStrategyProviderFactory — 6 слоёв абстракции ради эндпоинта, который возвращает список товаров — Интерфейс с единственной реализацией «на будущее» Такие проекты всегда «чистые». И на каждом из них новый разработчик тратит две недели, чтобы найти бизнес-логику. Откройте исходники любого успешного фреймворка в вашей экосистеме. God-классы, методы на 80 строк, комменты «don't ask why». Работает, развивается, приносит деньги. Моё мнение: → Код должен быть понятен через 6 месяцев. Не «чист» — а понятен. → Абстракция оправдана, когда у неё больше одной реализации прямо сейчас, а не «потенциально». → YAGNI важнее SOLID. Книгу стоит прочитать, принять к сведению, понять фундаментальные основы. Но не применять подходы в каждом методе. 💬 Пишите в комменты Ваше мнение

🔍 Ловим каждый SQL-запрос в Laravel Дебажить «а что вообще улетело в базу?» зачастую непросто. Но через DB::listen() можно перехватить каждый запрос вместе с биндингами и временем выполнения.
DB::listen(function (QueryExecuted $query) {
    dump($query->sql);      // select * from `users` where `id` = ? limit 1
    dump($query->bindings); // [0 => 1]
    dump($query->time);     // 6.05 (ms)
});
По сути, это не только про дебаг. Можно слать алерт в Slack, если запрос тормозит дольше порога. А для полного лога сессии есть связка DB::enableQueryLog() + DB::getRawQueryLog(). Кто-нибудь использует это в проде (или только whenQueryingForLongerThan)? Библиотека пхпшника

Какой из перечисленных алгоритмов хэширования поддерживается функцией password_hash()?
Anonymous voting

📌 Зачем дата-сайентисту матанализ? Основная компетенция специалиста по Data Science – способность анализировать и интерпрети
+6
📌 Зачем дата-сайентисту матанализ? Основная компетенция специалиста по Data Science – способность анализировать и интерпретировать данные, а математика является фундаментом для начала работы. В карточках мы разбираем основные разделы математики, с которых стоит начать изучение специалисту по анализу данных. Хотите подготовиться к офферу или подтянуть знания? Оставляйте заявку на наш курс по математике для Data Science 💙 P.S. Только до 31 мая на курс (и вообще на все программы Академии) действует СКИДКА 40% А как у вас дела с высшей математикой? ❤️ — Помню всё 🔥 — Знаю основы 🌚 — Ничего не знаю 🏃‍♀️ Proglib Academy

⚔️ nwidart vs internachi Считается, что internachi/modular быстрее nwidart/laravel-modules, потому что тащит модули через нативный Composer, а не сканирует module.json. Автор прогнал 50 запросов на батч от 25 до 200 модулей на Laravel 13 / PHP 8.4 — и цифры рушат это утверждение. ⚡️ Что показал замер с OPcache ON: — на 25–175 модулях nWidart стабильно быстрее по бутстрапу (+12 мс на каждые 25 модулей, линейно); — у internachi на 75–100 модулях нелинейный спайк от резолва classmap; — перелом наступает только на 200 модулях, где modules:cache даёт 621 мс против 1521 мс у nWidart — в 2.4 раза быстрее; — по памяти internachi выигрывает всегда: на 10–12 МБ меньше на запрос (registry nWidart живёт в куче, classmap — в shared memory OPcache). OPcache режет время бута у internachi на ~49%, у nWidart — только на ~33%. Логично: байткод кэшируется, а чтение module.json на каждом запросе — нет. 📊 Инженерный вывод: до 50 модулей разница в пределах шума, можно руководствоваться удобством DX. На 50–175 nWidart предсказуемее, а свыше 175 спасает только internachi с modules:cache, иначе линейный скан сильно замедлит работу. 🔗 Репа с данными

🔥 База по экономике токенов и кэшированию от AI Platform Lead из Bitrix24 Знакомьтесь, Сергей Нотевский. AI Platform Lead в
🔥 База по экономике токенов и кэшированию от AI Platform Lead из Bitrix24 Знакомьтесь, Сергей Нотевский. AI Platform Lead в Bitrix24. Он один из ключевых экспертов нашего курса AgentOps. На своих лекциях он детально разбирает экономику AI-агентов, кэширование токенов, LLM-инфраструктуру и вывод генеративных систем в стабильный прод. Мы попросили Сергея поделиться материалами для тех, кто хочет оптимизировать косты на LLM в проде. Сохраняйте методичку по prefix cache метрике, которая напрямую влияет на ваши деньги. Как говорят создатели Manus:
“KV-cache hit rate is the single most important metric for a production-stage AI agent.”
🛠 Что внутри методички (комбо из 3 статей + код):
Экономика кэширования — особенности провайдеров и как правильно считать затраты. Частые анти-паттерны — почему ваш кэш постоянно сбрасывается и вы платите больше. Кэш в AI-агентах — специфика работы с памятью в автономных системах.
🍒 Вишенка на торте: готовый SKILL для агента, который делает ревью вашего проекта, находит анти-паттерны и предотвращает низкое попадание в кэш. — Забрать комбо-материалы на GitHub P.S. Если хотите послушать Сергея вживую — ловите его на конференциях Kode Waves (май), Conversations AI и Highload Spb (июнь). 🎁 Акция в честь старта продаж! Прямо сейчас при покупке Инженерного трека вы получаете полный доступ к материалам курса «Разработка ИИ-агентов» в подарок. 👉 Забрать 2 курса по цене 1 и начать обучение

🚀 Laravel 13.6.0: дебаунс для очередей из коробки Частое сохранение документа плодит в очереди дублирующиеся задачи переиндексации. Раньше спасал интерфейс ShouldBeUnique, который блокирует диспатчи на входе. Теперь добавлен полноценный debounce — выполняется только последняя задача. Достаточно повесить атрибут на класс, и все дубли в заданном временном окне схлопываются на этапе выполнения:
#[DebounceFor(30, maxWait: 120)]
class RebuildSearchIndex implements ShouldQueue
{
    public function __construct(public int $documentId) {}

    public function debounceId(): string
    {
        return (string) $this->documentId;
    }

    public function handle(): void
    {
        SearchIndex::rebuild($this->documentId);
    }
}
Запустить дебаунс можно и без правки класса: dispatch(new SyncData($id))->debounceFor(30). Другие обновления релиза:роут /up отдает JSON по заголовку Accept (полезно для балансировщиков); — добавлен JsonFormatter для структурных логов; — появился транспорт Cloudflare Email. 🔗 Читать подробнее Библиотека пхпшника #release_radar

🔥 Еще с Laravel 8 появился Prunable С его помощью вы можете удалять старые модели по расписанию. Вам больше не нужно писать
🔥 Еще с Laravel 8 появился Prunable С его помощью вы можете удалять старые модели по расписанию. Вам больше не нужно писать пользовательские команды. Библиотека пхпшника #vardump

😎 Знакомьтесь с экспертом Proglib.academy: AI-архитектор Андрей Носов Андрей — один из ключевых спикеров нашего курса AgentO
😎 Знакомьтесь с экспертом Proglib.academy: AI-архитектор Андрей Носов Андрей — один из ключевых спикеров нашего курса AgentOps. Он выстраивает архитектуру, которая выживает в суровом проде и активно делится своим опытом. За что его ценит IT-комьюнити: 🟣 Топ-спикер AI Conf 2026
Его доклад про мифы семантического поиска и провалы Naive RAG стал одним из самых рейтинговых на конференции.
🟣 Эксперт по GraphRAG и Knowledge Graphs
Андрей внедряет инженерный подход в сложные системы, заменяя «слепую веру» в эмбеддинги строгой логикой графов.
🟣 Автор «14 кругов ада для RAG»
Разработал уникальный набор из 14 unit-тестов, на которых ломается стандартный векторный поиск (от слепоты к отрицаниям до конфликта версий).
🟣 Спикер Saint HighLoad
Регулярно выступает на крупнейших хайлоад-площадках, разбирая архитектуру отказоустойчивых ИИ-сервисов.
Андрей упаковал свои наработки в Google Colab, где можно пощупать 14 сценариев ошибок RAG и их решения: 🔗 Забрать Colab-ноутбук На курсе Андрей отвечает за самые «мясные» блоки: RAG, оркестрацию агентов и их промышленную эксплуатацию. Узнать больше о программе и обучении у Андрея: 👉 Курс о том, как внедрять AI-логику в бэкенд и сохранять стабильность сервиса Так, продолжаем знакомить вас с командой? 👍 — Да, ждем новых лиц 🔥 — Пойду тестить Colab Носова

🔧 Работаем с kubectl Под завис в Pending, а вы не знаете почему. Нет ресурсов, не тот nodeSelector или PVC не биндится? kubectl describe pod покажет секцию Events — там Kubernetes прямым текстом пишет причину. 🔹 Зачем это нужно — Events содержат сообщения от scheduler, kubelet и controller manager. — Показывает FailedScheduling с причиной: Insufficient cpu, node affinity mismatch, и т.д. — Видны ошибки pull-а образов, mount томов, readiness/liveness probe failures. 🔹 Как использовать — Полное описание пода: kubectl describe pod my-pod — Смотреть только Events (хак): kubectl describe pod my-pod | grep -A 20 "Events:" — События всего неймспейса: kubectl get events --sort-by='.lastTimestamp' — Только warning-и: kubectl get events --field-selector type=Warning — Следить за новыми: kubectl get events -w 💡 Про-тип: Events живут только 1 час по умолчанию. Если под висит в Pending давно и Events пустые, посмотрите kubectl get events -A --sort-by='.lastTimestamp', возможно, событие уже из другого неймспейса.

✔️ PHP-тест: клон, который мутирует оригинал Пользователь нажал «Повторить заказ». Цены в его старом заказе изменились. 📦 Задание Фича: кнопка «Повторить заказ» в личном кабинете. Копирует предыдущий заказ, применяет промокод, создаёт новый черновик. Оригинал помечается флагом repeated для аналитики. Через неделю — тикет от бухгалтерии: суммы в старых заказах не сходятся с тем, что было при оплате. Проблема только у заказов, которые хотя бы раз «повторяли». Суммы занижены ровно на размер скидки по промокоду.
// src/Order/Order.php
class Order
{
    public function __construct(
        private ?int   $id,
        private int    $userId,
        private array  $items, 
        private string $status,
        private bool   $repeated = false,
    ) {}

    public function getId(): ?int      { return $this->id; }
    public function getItems(): array  { return $this->items; }
    public function getStatus(): string { return $this->status; }

    public function resetForRepeat(): void
    {
        $this->id       = null;
        $this->status   = 'draft';
        $this->repeated = false;
    }

    public function markAsRepeated(): void
    {
        $this->repeated = true;
    }

    public function calculateTotal(): int
    {
        return array_sum(array_map(
            fn(OrderItem $i) => $i->getSubtotal(),
            $this->items
        ));
    }
}

// src/Order/OrderItem.php
class OrderItem
{
    public function __construct(
        private int $productId,
        private int $qty,
        private int $price,
    ) {}

    public function getProductId(): int { return $this->productId; }
    public function getQty(): int       { return $this->qty; }
    public function getPrice(): int     { return $this->price; }

    public function getSubtotal(): int
    {
        return $this->qty * $this->price;
    }

    public function applyDiscount(int $percent): void
    {
        $this->price = (int) round(
            $this->price * (1 - $percent / 100)
        );
    }
}

// src/Order/RepeatOrderHandler.php
class RepeatOrderHandler
{
    public function __construct(
        private OrderRepository $orders,
        private PromoService    $promo,
    ) {}

    public function handle(int $originalId, ?string $promoCode): Order
    {
        $original = $this->orders->findById($originalId);

        $copy = clone $original;
        $copy->resetForRepeat();

        if ($promoCode !== null) {
            $discount = $this->promo->resolve($promoCode);

            foreach ($copy->getItems() as $item) {
                $item->applyDiscount($discount->percent);
            }
        }

        $this->orders->save($copy);

        $original->markAsRepeated();
        $this->orders->save($original);

        return $copy;
    }
}

// src/Repository/OrderRepository.php
class OrderRepository
{
    public function __construct(private PDO $pdo) {}

    public function save(Order $order): void
    {
        if ($order->getId() === null) {
            $this->insert($order);
        } else {
            $this->update($order);
        }
    }

    private function update(Order $order): void
    {
        $this->pdo->prepare(
            'UPDATE orders SET status = ?, repeated = ? WHERE id = ?'
        )->execute([$order->getStatus(), (int) $order->isRepeated(), $order->getId()]);

        $this->pdo->prepare('DELETE FROM order_items WHERE order_id = ?')
            ->execute([$order->getId()]);

        foreach ($order->getItems() as $item) {
            $this->pdo->prepare(
                'INSERT INTO order_items (order_id, product_id, qty, price) VALUES (?, ?, ?, ?)'
            )->execute([$order->getId(), $item->getProductId(), $item->getQty(), $item->getPrice()]);
        }
    }
}
🔹 Задачи — Объяснить, каким образом цены в оригинальном заказе оказались изменены в базе — Исправить код так, чтобы оригинал гарантированно не мутировал Ставьте → 🔥 если нравится формат. Если нет → 🌚 💬 Решения пишите в комменты под спойлер — сравним подходы.

💡 Затрагиваемые отношения Eloquent Laravel автоматически обновляет updated_at в ManyToMany отношениях, а также поставляется
💡 Затрагиваемые отношения Eloquent Laravel автоматически обновляет updated_at в ManyToMany отношениях, а также поставляется с методом setTouchedRelations для ручного обновления связанных моделей в отношениях OneToOne и OneToMany. 🐸 Библиотека пхпшника #vardump