Powrót do bazy wiedzy

Własne Moduły: Rozszerz Magento Bezpiecznie

Modyfikacja core Magento 2 to pewna droga do katastrofy przy każdej aktualizacji. Dowiedz się, jak tworzyć własne moduły z Plugins, DI i Declarative Schema, które przetrwają każdy upgrade i działają niezawodnie na produkcji.

0

modyfikacji core – wszystko przez Plugins i Preferences

DI

Dependency Injection – podstawa testowalnego i elastycznego kodu

PSR-12

Magento Coding Standard – wymagany do przejścia code review

Magento 2 zostało zaprojektowane tak, żeby można je było rozszerzać bez ingerencji w kod źródłowy. Każda zmiana zachowania platformy powinna odbywać się przez dedykowany mechanizm rozszerzeń: Plugins do metod, Preferences do podmienienia klas, Observers do zdarzeń i Declarative Schema do zmian w bazie danych. To gwarantuje, że Twój moduł będzie działał po każdej aktualizacji Magento.

Struktura i rejestracja modułu

Każdy moduł Magento 2 to katalog w app/code/Vendor/ModuleName/ z minimalnymi plikami rejestracyjnymi. Bez nich Magento nie rozpozna Twojego kodu. Sekcja <sequence> w module.xml kontroluje kolejność ładowania – jeśli Twój moduł nadpisuje moduł bazowy, musi się ładować po nim.

Minimalna struktura modułu + rejestracja

Dwa pliki wymagane do rejestracji modułu oraz komendy aktywacji. Bez setup:upgrade Magento nie wykryje zmian w schemacie bazy danych.

// app/code/Vendor/ModuleName/registration.php

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(

  ComponentRegistrar::MODULE,

  'Vendor_ModuleName',

  __DIR__

);

<!-- app/code/Vendor/ModuleName/etc/module.xml -->

<config>

  <module name="Vendor_ModuleName" setup_version="1.0.0">

    <sequence><module name="Magento_Catalog"/></sequence>

  </module>

</config>

# Aktywacja modułu:

php bin/magento module:enable Vendor_ModuleName

php bin/magento setup:upgrade && php bin/magento setup:di:compile

Plugins (Interceptors) – najważniejszy mechanizm rozszerzeń

Plugins to podstawowy sposób rozszerzania zachowania klas Magento 2 bez ich modyfikacji. Pozwalają na uruchomienie kodu przed (before), po (after) lub zamiast (around) oryginalnej metody. Są bezpieczne, łatwe w testowaniu i nie kolidują z innymi modułami (kilka Pluginów może działać jednocześnie na tej samej metodzie).

Pro Tip: Plugin after vs around – kiedy użyć czego?

Użwaj around tylko gdy musisz warunkowo zapobiec wywołaniu oryginalnej metody. We wszystkich innych przypadkach before lub after są lepsze – są szybsze i nie blokują innych Pluginów w łańcuchu wywołań.

<!-- etc/di.xml -->

<type name="Magento\Catalog\Model\Product">

  <plugin name="vendor_module_product_plugin"

    type="Vendor\ModuleName\Plugin\ProductPlugin"/>

</type>

// Plugin/ProductPlugin.php

public function afterGetName(Product $subject, string $result): string {

  return $result . ' [OUTLET]'; // dołącz tekst po nazwie

}

public function beforeSetPrice(Product $subject, float $price): array {

  return [$price * 0.9]; // rabat 10% przed zapisem

}

Declarative Schema – zmiany w bazie bez Install Scripts

Od Magento 2.3 migracje bazy danych powinny być deklarowane w pliku etc/db_schema.xml. To lepsze podejście niż stare InstallSchema/UpgradeSchema – Magento sam wykrywa różnice i stosuje tylko niezbędne ALTER TABLE. Nie musisz się martwić o wersjonowanie skryptów.

db_schema.xml + wygenerowanie whitelist

Przykład dodania nowej tabeli z kluczem obcym do produktu. Po każdej zmianie db_schema.xml musisz wygenerować plik db_schema_whitelist.json.

<!-- etc/db_schema.xml -->

<schema>

  <table name="vendor_custom_data" resource="default" engine="innodb">

    <column name="entity_id" xsi:type="int" unsigned="true" nullable="false" identity="true"/>

    <column name="product_id" xsi:type="int" unsigned="true" nullable="false"/>

    <column name="custom_value" xsi:type="varchar" length="255" nullable="true"/>

    <constraint xsi:type="primary" referenceId="PRIMARY">

      <column name="entity_id"/>

    </constraint>

  </table>

</schema>

# Wygeneruj whitelist po każdej zmianie schematu:

php bin/magento setup:db-declaration:generate-whitelist --module-name=Vendor_ModuleName

# Zastosuj zmiany w bazie:

php bin/magento setup:upgrade

Kiedy użyć jakiego mechanizmu?

Plugin – modyfikacja metody klasy

Zmień zachowanie przed/po/zamiast konkretnej metody publicznej. Nie wymaga nadpisywania całej klasy. Preferowany mechanizm rozszerzeń.

Preference – podmiana całej klasy

Używaj tylko gdy Plugin nie wystarczy (np. zmiana prywatnych metod). Twoja klasa dziedziczy z oryginalnej i nadpisuje wybrane metody.

Observer – reakcja na zdarzenie

Niezbędny gdy chcesz reagować na eventy Magento (np. sales_order_place_after). Nie blokuje wywołania oryginalnego kodu.

Cron Job – zadania cykliczne

Zdefiniuj w etc/crontab.xml. Magento zarządza kolejką crona niezależnie od systemu – sprawdzaj tabelę cron_schedule.

API REST/GraphQL – nowy endpoint

Zdefiniuj w etc/webapi.xml i etc/schema.graphqls. Dostęp kontrolowany przez ACL (etc/acl.xml).

UI Component – rozszerzenie panelu Admin

Dodaj kolumny do gridów, nowe pola w formularzach lub całkowicie nowe sekcje w Adminie przy użyciu XML i knockout.js binding.

Najczęstsze błędy przy tworzeniu modułów

Modyfikacja plików w vendor/

Każdy composer update nadpisze zmiany. Zawsze użwaj Plugins lub Preferences zamiast edytować kod core Magento.

Brak setup:di:compile po zmianie DI

Zmiany w etc/di.xml lub nowe klasy nie działają w trybie production bez rekompilacji kontenera DI.

ObjectManager użyty bezpośrednio

Używanie ObjectManager::getInstance() w kodzie to antywzorzec. Wstrzykuj zależności przez konstruktor – kod będzie testowalny i czytelny.

Błędna kolejność w sequence

Plugin lub Preference ładuje się przed modułem bazowym i nie działa. Sprawdź sekcję <sequence> w module.xml.

Brak whitelist dla db_schema

Po dodaniu kolumny do db_schema.xml bez regeneracji whitelist.json Magento nie zastosuje zmian lub zgłosi błąd przy setup:upgrade.

Naruszenie Magento Coding Standard

Moduł nie przechodzi code review. Uruchom vendor/bin/phpcs --standard=Magento2 app/code/Vendor/ przed każdym commitem.

Przydatne komendy deweloperskie

Zestaw komend, które przyspieszą development i debugging modułów Magento 2.

# Włącz tryb deweloperski (szybsze iteracje, widoczne błędy):

php bin/magento deploy:mode:set developer

# Wyczyść wygenerowane pliki DI i cache:

rm -rf generated/code/* generated/metadata/* var/cache/* var/page_cache/*

php bin/magento cache:flush

# Sprawdź zależności modułu (co zależy od twojego modułu):

php bin/magento module:status Vendor_ModuleName

# Analiza statyczna PHPCS ze standardem Magento2:

vendor/bin/phpcs --standard=Magento2 app/code/Vendor/ModuleName/ --extensions=php

# Wygeneruj interfejs Data Object (Value Object):

php bin/magento dev:generate:api:data-object --module=Vendor_ModuleName

# Debugowanie pluginu – lista wszystkich pluginów na metodzie:

php bin/magento dev:di:info "Magento\Catalog\Model\Product"

Tworzenie modułów Magento 2 to rzemiosło wymagające znajomości architektury platformy. W Mage24.pl każdy nasz moduł przechodzi przez code review, testy PHPUnit i analizę PHPCS – zanim trafi na produkcję klienta.

Potrzebujesz dedykowanego modułu Magento 2?

Zaprojektujemy i wdrożymy moduł zgodny z najlepszymi praktykami Magento – z testami, dokumentacją i gwarancją kompatybilności z przyszłymi wersjami.

Zapytaj o Moduł