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
+
:::