Пастки

← Пастки

Ashterix

docs(articles): From Magento to Symfony, a requalification guide grouped into sections

uk/articles/magento-to-symfony/quality/traps.md новий файл +81 −0

1 + # Пастки
2 +
3 + Де Magento-досвід найчастіше підводить. Червоні блоки — пастки, що псують дані, жовті коштують часу.
4 +
5 + ## flush() пише все
6 +
7 + :::danger subtitle="Дані"
8 + Не лише «цю» сутність, а кожну змінену в UnitOfWork. `flush($entity)` в ORM 3 прибрано. Тримайте flush у точці входу і не змінюйте сутності, які не збираєтесь зберігати.
9 + :::
10 +
11 + ## Стан у властивостях сервісу
12 +
13 + :::danger subtitle="Дані"
14 + Сервіси спільні, а воркер Messenger живе годинами й обробляє тисячі повідомлень. Кеш, поточний користувач чи замовлення у властивості сервісу протікають між повідомленнями. Реалізуйте `ResetInterface` або не тримайте стан.
15 + :::
16 +
17 + ## EntityManager is closed
18 +
19 + :::danger subtitle="Дані"
20 + Після винятку під час flush EntityManager закривається, і наступні операції падають. Не ловіть виняток, щоб продовжити тим самим EM. У воркерах Messenger про це дбає middleware Doctrine; у своїх циклах — `ManagerRegistry::resetManager()`.
21 + :::
22 +
23 + ## N+1 на лінивих зв'язках
24 +
25 + :::warning subtitle="Продуктивність"
26 + Звичка «колекція, а потім getX() у циклі» тут генерує запит на кожну ітерацію. Дивіться лічильник запитів у профайлері і робіть fetch join.
27 + :::
28 +
29 + ## Зміни всередині об'єкта не видно
30 +
31 + :::warning subtitle="Дані"
32 + Doctrine порівнює значення, а не вміст об'єктів. `$this->date->modify('+1 day')` на mutable `DateTime` не збережеться. Використовуйте `DateTimeImmutable` і присвоюйте нове значення; так само з масивами-об'єктами в JSON-колонках.
33 + :::
34 +
35 + ## Inverse side не зберігається
36 +
37 + :::warning subtitle="Дані"
38 + У двосторонньому зв'язку в БД пишеться лише owning side. Додавайте хелпери, що оновлюють обидві сторони.
39 + :::
40 +
41 + ## cache:clear не чистить дані
42 +
43 + :::warning subtitle="Час"
44 + Системний кеш і пули — різні речі. Застарілі дані в Redis лишаються після `cache:clear`; для них `cache:pool:clear` або інвалідація тегами.
45 + :::
46 +
47 + ## $container->get() не працює
48 +
49 + :::warning subtitle="Час"
50 + Сервіси приватні, тож ObjectManager-підхід неможливий. Якщо сервіс треба вибрати в runtime, використайте `#[AutowireLocator]`.
51 + :::
52 +
53 + ## Невикористаний сервіс зникає
54 +
55 + :::warning subtitle="Час"
56 + Контейнер видаляє приватні сервіси, які ніхто не інжектує. У тестах `getContainer()->get()` такого сервісу кидає помилку; це не баг конфігу.
57 + :::
58 +
59 + ## Порядок слухачів має значення
60 +
61 + :::warning subtitle="Безпека"
62 + Роутер на kernel.request має пріоритет 32, firewall — 8. Слухач з пріоритетом 20 виконається до автентифікації і не бачить користувача. Перевіряйте через `debug:event-dispatcher`.
63 + :::
64 +
65 + ## Старий код у воркерах
66 +
67 + :::warning subtitle="Деплой"
68 + Воркер тримає код у пам'яті. Після деплою — `messenger:stop-workers`, інакше повідомлення обробляє попередня версія.
69 + :::
70 +
71 + ## Секрети в .env
72 +
73 + :::warning subtitle="Безпека"
74 + `.env` комітиться, тому в ньому лише значення за замовчуванням для dev. Справжні ключі — у змінних середовища сервера або в `secrets:set`.
75 + :::
76 +
77 + ## Перенесення Magento-шарів один в один
78 +
79 + :::warning subtitle="Архітектура"
80 + Api/Data-інтерфейс, Repository-обгортка над репозиторієм, Management-сервіс на кожну сутність — це церемонія без користі в застосунку, яким ви володієте. Додавайте шар, коли з'являється реальна причина.
81 + :::