Magento 2: Jak moduł oddziałuje z innymi modułami?
Magento 2 jest zgodne z PSR-4. Jako główną zasadę interakcji modułów Magento 2 deklaruje wzorzec wstrzykiwania zależności DI (ang. depencency injection) oraz usługi serwisowe (ang. service contractors). Jedną z ważnych części interakcji modułów jest obszar kodu (ang. code area) Magento. Wszystkie komponenty współpracują z systemem i innymi komponentami w zakresie domyślnych obszarów.
Zależności modułów
Moduły mogą zawierać zależności od następujących składników oprogramowania:
- Inne moduły Magento,
- Rozszerzenia PHP,
- Biblioteki zewnętrzne (ang. third party libraries).
Obszary Magento
Obszary Magento organizują kod pod optymalizację przetwarzania żądań przez ładowanie części komponentów, które są związane tylko z określonym obszarem.
Magento posiada 7 typów obszarów:
- Magento Admin (adminhtml): punktem wejścia tego obszaru jest index.php lub pub/index.php. Zawiera kod do zarządzania sklepem.
- Storefront (frontend): punktem wejścia tego obszaru jest plik index.php lub pub/index.php. Storefront (lub frontend) zawiera szablony (ang. templates) i układy stron (ang. layout), które definiują wygląd sklepu.
- Basic (base): używany jako rozwiązanie zastępcze dla plików nieobecnych w obszarach adminhtml
i frontend. - Cron (crontab): W pliku pub/cron.php, klasa Magento\Framework\App\Cron zawsze ładuje obszar ’crontab’.
- Web API REST (webapi_rest): punktem wejściowym dla tego obszaru jest index.php lub pub/index.php. Obszar REST ma front controller, który rozumie jak wyszukiwać adresy URL oparte na protokole REST.
- GraphQL (grapql): punktem wejściowym dla tego obszaru jest plik index.php lub pub/index.php
- Web API SOAP (webapi_soap): punktem wejściowym dla tego obszaru jest plik index.php lub pub/index.php.
Zarządzanie zależnościami modułów
Zależności modułu mogą być zarządzane przez:
- Nazwę i deklarację tego modułu w pliku module.xml,
- Deklarację wszelki zależności, jakie posiada moduł (czy to na innych modułach, czy na innym komponencie) w pliku composer.json modułu,
- (opcjonalnie) Definicja pożądanej kolejności ładowania plików konfiguracyjnych w pliku module.xml.
Kiedy mamy dwa moduły o nazwie Anna_GuestbookAdminUI oraz Anna_Guestbook. Żeby określić, że moduł Anna_GuestbookAdminUI jest zależny od modułu Anna_Guestbook należy w pliku module.xml należącym do Anna_GuestbookAdminUI dodać do listy Anna_Guestbook. Za pomocą węzła <sequence> dodajemy wspomniany moduł, co sprawi, że będzie on załadowany przed modułem Anna_GuestbookAdminUI.
1 2 3 4 5 6 7 8 9 |
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Anna_GuestbookAdminUI" setup_version="0.0.1"> <sequence> <module name="Anna_Guestbook" /> </sequence> </module> </config> |
Dodatkowo potrzebujemy taką zależność określić jeszcze w pliku composer.json, który należy do modułu Anna_GuestbookAdminUI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
{ "name": "anna/module-guestbook-admin-ui", "description": "N/A", "type": "magento2-module", "config": { "sort-packages": true }, "require": { "php": "~7.1.3||~7.2.0||~7.3.0", "magento/framework": "102.0.*", "anna/guestbook": "*" }, "suggest": {}, "autoload": { "files": [ "registration.php" ], "psr-4": { "Anna\\Anna_GuestbookAdminUI\\": "" } } } |
Typy zależności
Przyjrzymy się teraz typom zależności. Mamy dwie typy zależności: twarda (ang. hard) i miękka (ang. soft).
Zależność twarda
Moduły z twardą zależnością z innym modułem nie mogą funkcjonować bez modułu, od którego zależą. W szczególności:
- Moduł zawiera kod, który bezpośrednio używa logiki z innego modułu, np. instancje drugiego modułu, stałe klas, metody statyczne, właściwości publiczne klas, interfejsy, cechy.
- Moduł zawierający ciągi znaków zawierające nazwy klas, nazwy metod, stałe klas, właściwości klas, interfejsy i cechy z innego modułu.
- Moduł deserializuje obiekt zadeklarowany w innym module.
- Moduł wykorzystuje lub modyfikuje tabele bazy danych używane przez inny moduł.
Przykład omawiamy w dalszej części w sekcji: Przykład zależności twardej.
Zależność miękka
Moduły z miękką zależnością od innego modułu mogą poprawnie działać bez innego modułu, nawet jeśli ma od niego zależności. W szczególności, gdy:
- Moduł sprawdza bezpośrednio dostępność innego modułu,
- Moduł rozszerza konfigurację innego modułu,
- Moduł rozszerza układ strony (layout) innego modułu.
Nieodpowiednie zależności
Tworzenia pewnych rodzaju zależności należy unikać:
- Kołowe (bezpośrednie i pośrednie),
- Niezadeklarowane,
- Niepoprawne.
Kolejność przejścia instalacji modułów
Kolejność instalacji modułów w Magento jest następująca:
- Najpierw moduły, które są zależnościami dla innych modułów,
- Moduły, które mają zależności.
Zależności między modułami w różnych warstwach
Moduł, który należy do warstwy aplikacji nie może być użyty w frameworku Commerce.
Można budować zależności pomiędzy klasami w warstwie aplikacji, ale te klasy muszą należeć do tego samego modułu. Zależności pomiędzy modułami powinny być budowane wyłącznie przez umowę serwisową (ang. contract service) lub interfejs dostawcy usługi (ang. SPI – service provider interface).
Interfejs dostawcy usługi to interfejs API przeznaczony do wdrożenia lub rozszerzenia przez innych producentów. Można go włączyć do rozszerzenia framerowka oraz do komponentów wymiennych.
Jeśli chodzi o warstwę Framework. Moduł należący do frameworka Commerce może być używany w warstwie aplikacji poprzez jawną zależność.
Jak Magento w kodzie sprawdza zależności?
Magento 2 posiada 3 klasy parserów, które sprawdzają zależności, jakie występują pomiędzy modułami:
- Magento\Setup\Module\Dependency\Parser\Code (kod): Sprawdza klasy użyte w kodzie,
- Magento\Setup\Module\Dependency\Parser\Config\Xml (kod): Sprawdza zależności w deklaracji modułu,
- Magento\Setup\Module\Dependency\Parser\Composer\Json (kod): Sprawdza zależności zawarte w pliku composer.json.
Tylko parser composer’a oferuję rozróżnienie na zależności twarde i miękkie. W zależności od tego gdzie w sekcji package dodamy moduł. Zależności twarde dodajemy do sekcji require zaś miękkie to sekcji suggest. Domyślnym typem zależności są twarde, dlatego inne parsery traktują znalezione zależności jako twarde. Wszystkie parsery implementują interfejs Magento\Setup\Module\Dependency\ParserInterface (kod tutaj).
Generowanie raportu zależności pomiędzy modułami
Magento pozwala również wygenerować odpowiedni raport z informacją o zależnościach pomiędzy modułami czy samym frameworkiem.
1 |
bin/magento info:dependencies:{show-modules|show-modules-circular|show-framework} [-d|--directory="<path>"] [-o|--output="<path and filename"] |
Znaczenie parametrów dla powyższego polecenia są następujące:
- typ raportu (wymagany):
- show-modules — raport zależności modułów,
- show-modules-circular — raport zależności kołowych,
- show-framework — raport zależności od frameworka,
- -d lub –directory — ścieżko do bazowego katalogu, gdzie ma się rozpocząć wyszukiwanie danych dla wybranego raportu,
- -o lub –output — pozwala określić ścieżkę bezwzględną i nazwę pliku. Wygenerowany plik raportu posiada wartości rozdzielone przecinkami i zapisywany jest w formacie CSV.
Po więcej informacji odsyłam do dokumentacji Dependency reports.
Przykład zależności twardej
Co się może stać, jak chcemy wyłączyć wybrany moduł, który jest zależnością.
Spróbujmy wyłączyć moduł odpowiedzialny za autoryzację dwuetapową
Za pomocą komendy wyłączającej moduł:
1 |
bin/magento module:disable Magento_TwoFactorAuth |
W konsoli dostajemy informację, że ten moduł jest wykorzystywany przez inny moduł: Magento_AdminAdobeImsTwoFactorAuth
Więc najpierw będziemy potrzebowali wyłączyć moduł Magento_AdminAdobeImsTwoFactorAuth.
Tym razem operacja się wykonała. Konsola wyświetla również dodatkowe informacje i dalsze kroki:
W trybie developer (mode, na którym pracuje Magento sprawdzamy za pomocą komendy bin/magento deploy:mode:show) nie musimy tego robić.
W przypadku trybu produkcyjnego potrzebujemy wykonać takie komendy jak:
- Jeśli jest taka potrzeba, usunięcie statycznej zawartości wygenerowanej przez ten moduł. Robimy to podczas wyłączania określonego modułu, na przykład:
1 |
bin/magento module:disable Magento_AdminAdobeImsTwoFactorAuth --clear-static-content |
- wygenerowanie od nowa listy klas
1 |
bin/magento setup:di:compile |
Przyjrzyjmy się teraz sami zależnościami. W module Magento_AdminAdobeImsTwoFactorAuth mamy plik module.xml o następującej zawartości:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0"?> <!-- /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Magento_AdminAdobeImsTwoFactorAuth"> <sequence> <module name="Magento_AdminAdobeIms"/> <module name="Magento_TwoFactorAuth"/> </sequence> </module> </config> |
To są twarde zależności, dlatego też w pliku composer.json tego modułu, mamy dodane te moduły do części z require:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
{ "name": "magento/module-admin-adobe-ims-two-factor-auth", "description": "This module is used to add Admin Adobe Ims and Two Factor Auth dependency.", "type": "magento2-module", "license": "OSL-3.0", "version": "1.0.0", "require": { "php": "~8.1.0||~8.2.0", "magento/framework": "*", "magento/module-admin-adobe-ims": "100.5.*", "magento/module-two-factor-auth": "*" }, "autoload": { "files": [ "registration.php" ], "psr-4": { "Magento\\AdminAdobeImsTwoFactorAuth\\": "" } } } |
Dlatego, ostatecznie żeby wyłączyć interesujący ten moduł, potrzebne było wydanie następujących komend:
1 2 3 |
bin/magento module:disable Magento_AdminAdobeImsTwoFactorAuth bin/magento module:disable Magento_TwoFactorAuth bin/magento cache:flush |
Ostatnim krokiem było wyczyszczenie cache’a.
Skutki uboczne oddziaływania pomiędzy modułami
Skutki uboczne oddziaływania pomiędzy modułami mogą być następujące:
- Błędem, kiedy brakuje modułu lub moduł jest wyłączony,
- Błędem podczas wstrzykiwania brakującej klasy,
- Jeśli moduły zawierają pliki di.xml, takie pliki mogą czasami ładować się w niewłaściwej kolejności lub próbować nadpisać już nadpisaną funkcjonalność modułu. Aby rozwiązać tę sytuację, w pliku module.xml należy określić w <sequence> listę modułów, które mają zostać załadowane przed użyciem obecnego modułu.
Magento 2: Zdarzenia i obserwatory - Web Porgramming
12 października 2023 @ 15:11
[…] Magento implementuje wzorzec projektowy zdarzenia (ang. event) i obserwatora (ang. observer). Wzorzec ten daje nam możliwość modyfikacji w kluczowych miejscach przetwarzania w Magento. Dzięki temu możemy w łatwy sposób wiązać pomiędzy sobą różne moduły. Podstawy o tym, jak moduły oddziałują na siebie, zostały umieszczone we wpisie Magento 2: Jak Moduł Oddziałuje Z Innymi Modułami. […]
Tworzenie nowego kontrolera w Magento 2 - Web Programming
25 października 2023 @ 23:38
[…] AnnaFirstControlleretcfrontend – konfiguracja modułu dla obszaru frontend, […]
Magento 2: preference - Web Programming
3 listopada 2023 @ 22:19
[…] tu pod uwagę kolejność, z jaką moduły są ładowane, tutaj istotne jest również określenie zależności twardej. Poniżej plik […]
Dodanie akcji do istniejącego kontrolera w Magento 2 - Web Programming
7 listopada 2023 @ 17:52
[…] jest, aby pamiętać o zależnościach pomiędzy innymi modułami. Jako że chcemy wykorzystać istniejący routing, potrzebujemy w module zaznaczyć, że przed jego […]
Pluginy w Magento 2 - Web Programming
4 grudnia 2023 @ 02:58
[…] że przedstawiona tu modyfikacja dotyczy obszaru frontend, tworzę plik w […]
Magento 2 tryby działania aplikacji - Web Programming
21 grudnia 2023 @ 03:38
[…] konfiguracji na obszar (zoptymalizowane konfiguracja wstrzykiwania zależności na […]
Magento 2: tworzenie kontrolera i menu w adminie - Web Programming
9 lutego 2024 @ 16:57
[…] AnnaAdminControlleretcadminhtml — konfiguracja dla modułu dla obszaru adminhtml, […]