Magento 2: Jak twórcy modułów powinni czytać własne pliki konfiguracyjne

20

Scenariusz: Jestem programistą modułu Magento 2. Chcę utworzyć plik konfiguracyjny w app/etc. Chcę, aby ten plik miał „zasięg” według obszaru

app/etc/my_file.xml
app/etc/frontend/my_file.xml
app/etc/adminhtml/my_file.xml

W Magento 1 stworzę i będę na dobrej config.xmldrodze. Określanie zasięgu nastąpiło w samym pliku XML. Jednak Magento 2 podchodzi do tego zupełnie inaczej

Jakie pliki klas należy utworzyć w Magento 2 do odczytu tych plików konfiguracyjnych o zasięgu. Ze źródła Magento 2 nie jest jasne, jaki „właściwy” sposób to zrobić. Kod podstawowy ma wiele podejść i żadne z nich nie jest oznaczone żadną @apimetodą. Utrudnia to ustalenie sposobu wykonywania tego wspólnego zadania programisty modułu. Jako wtórny efekt uboczny utrudnia również ustalenie, jak programista modułu Magento powinien czytać z podstawowych plików konfiguracyjnych.

Z jednej strony wydaje się, że „właściwą” rzeczą jest stworzenie obiektu czytnika systemu plików. Na przykład Magento wydaje się ładować import.xmlplik w następujący sposób

#File: vendor/magento/module-import-export/Model/Import/Config/Reader.php
namespace Magento\ImportExport\Model\Import\Config;

class Reader extends \Magento\Framework\Config\Reader\Filesystem
{

    public function __construct(
        //...
        $fileName = 'import.xml',
        //...
    ) {
        parent::__construct(
            $fileResolver,
            $converter,
            $schemaLocator,
            $validationState,
            $fileName,
            $idAttributes,
            $domDocumentClass,
            $defaultScope
        );
    }
    //...
}        

Magento\Framework\Config\Reader\FilesystemKlasa podstawowa wygląda tak, jakby zawierała kod do rozwiązania zakresu obszaru.

Jednak niektóre pliki konfiguracyjne Magento wydają się unikać tego wzoru. Chociaż istnieją czytniki tych plików ( event.xmlw tym przykładzie)

vendor/magento/framework/Event/Config/Reader.php

Istnieją również klasy danych o zasięgu, które korzystają z tych czytników.

#File: vendor/magento/framework/Event/Config/Data.php
class Data extends \Magento\Framework\Config\Data\Scoped
{
    public function __construct(
        \Magento\Framework\Event\Config\Reader $reader,
        //...
    ) {
        parent::__construct($reader, $configScope, $cache, $cacheId);
    }
}

To sprawia, że ​​wydaje się, że klasy czytników o zasięgu są tym, co programista powinien stworzyć. Ale nie wszystkie pliki konfiguracyjne mają czytniki o takim zasięgu.

Czy twórcy modułów Magento 2 mają jasną ścieżkę do naśladowania? Czy jest to coś, do czego twórcy modułów Magento 2 powinni podchodzić na swój własny sposób, a wynikający z tego chaos / niestandardowe ładowanie konfiguracji to tylko koszt prowadzenia działalności?

Oficjalna dokumentacja robi dobrą robotę, obejmujących niektóre z dostępnych klas, ale nic, co godzi fakt, że nie ma jasnych wytycznych, na których konkretna realizacja jesteśmy przypuszczać, aby użytku lub gdy oczekuje się, każdy moduł decyduje, jak to zrobić na jego posiadać.

Alan Storm
źródło
Myślę, że to może pomóc: magento.stackexchange.com/q/51915/146
Marius
Czy widziałeś ten PR autorstwa @vinai github.com/magento/magento2/pull/1410 ? Myślę, że jeśli nie masz specjalnych wymagań, możesz utworzyć własny plik konfiguracyjny za pomocą tylko typów wirtualnych.
Kristof at Fooman

Odpowiedzi:

4

Aby utworzyć nowy typ konfiguracji, programista modułu powinien utworzyć klasę typu konfiguracji, która będzie używana przez klientów konfiguracji.

Aby maksymalnie uprościć te typy typów, wszystkie zachowania związane z odczytywaniem plików konfiguracyjnych i buforowaniem danych zostały przeniesione do \Magento\Framework\Config\DataInterfacedwóch implementacji wielokrotnego użytku:

  • \Magento\Framework\Config\Data - dla typów konfiguracji, które mają sens tylko w jednym zakresie (eav_attributes.xml tylko w globalnym)
  • \Magento\Framework\Config\Data\Scoped - dla typów konfiguracji, które mogą być ładowane w różnych zakresach (events.xml - globalne i dla poszczególnych obszarów)

Każdy typ konfiguracji powinien mieć wstępnie skonfigurowany Config\DataInterfaceobiekt. Konfigurację można wykonać za pomocą typu wirtualnego lub dziedziczenia.

Chociaż twórca modułów może technicznie dziedziczyć typ konfiguracji po Config\DataInterfaceimplementacji, zaleca się, aby nie rozszerzać klas podstawowych. Zawsze lepiej używać kompozycji.

Teraz \Magento\Framework\Config\Datai Data\Scopedtylko zrobić buforowania i delegata konfiguracji do czytania \Magento\Framework\Config\ReaderInterface. ReaderInterfacema zapewnić poprawną konfigurację w formacie tablicy PHP dla żądanego zakresu (jeśli zakres ma konfigurację). Wiele implementacje ReaderInterfacesą możliwe (na przykład odczytać z konfiguracji DB), ale Magento tylko statki jednego czytnika ogólnego: \Magento\Framework\Config\Reader\Filesystem.

\Magento\Framework\Config\Reader\Filesystem wykonuje wszystkie operacje wymagane do odczytu plików z modułowego systemu plików: odczytuje pliki, łączy i sprawdza poprawność.

Każdy Config\DataInterfacepowinien mieć osobno skonfigurowaną instancję Config\ReaderInterface. Jak każdy przypadek w systemie, konkretny czytnik może być skonfigurowany albo z typem wirtualnym, albo z dziedziczeniem. Dokumentacja Magento Opisuje wszystkie Filesystemzależności.

Każdy element w tym łańcuchu jest opcjonalny (z wyjątkiem samej klasy typu konfiguracji) i można go zastąpić bardziej szczegółową implementacją.

Anton Kril
źródło
1

Wygląda na to, że oficjalna dokumentacja zawiera odpowiedzi na twoje pytanie.

KAndy
źródło
1
Dziękuję za odpowiedź, ale nie jestem pewien, czy dokumentacja odpowiada na moje pytanie. Zawiera listę wielu dostępnych interfejsów (co jest przydatne, +1), ale nie zgadza się z faktem, że żadna z konkretnych implementacji tych interfejsów ( Magento\Framework\Config\Datai Magento\Framework\App\Config) nie jest oznaczona @api. Gdybym miał tylko tę dokumentację, zakładałbym, że jako programista modułów nie ma standardowego systemu do tworzenia i odczytywania plików konfiguracyjnych i że mogę robić, co chcę. To nie wydaje się właściwe.
Alan Storm
Czy możesz opisać przypadki, w których musisz odczytać konfigurację dla innego modułu? Dla mnie czytnik konfiguracji to prywatny interfejs API modułu.
KAndy
Jeśli deweloper chciał przyczynić się do rdzenia Magento. Jeśli programista działa na wielu modułach, z których nie wszystkie kontrolują, i nie chce rozplątywać wykresu UML w celu odczytania wartości z pliku konfiguracyjnego. Zobacz także - większość innych frameworków PHP z systemem konfiguracji. Niezależnie od tego, jeśli intencją zespołu głównego Magento 2 jest to, że konfiguracja modułu jest prywatna i niestandardowa dla każdego modułu, należy to gdzieś podać.
Alan Storm
Również - (nieco inna / styczna) sekcja Konfiguracja systemu w zapleczu Magento - budowanie funkcji w oparciu o konfigurację istniejącej sekcji.
Alan Storm
2
Każdy interfejs API, który nie jest opatrzony adnotacją @api, jest prywatny w tym sensie, że jeśli go używasz, jesteś odpowiedzialny za wsteczną kompatybilność / zmiany interfejsu. \ Magento \ Framework \ Config \ ReaderInterface ma adnotację \ @api.
KAndy
0

W chwili pisania tego tekstu nie wydaje się standardem czytania scalonego drzewa konfiguracji w Magento 2. Każdy moduł implementuje własne klasy czytania konfiguracji, co oznacza, że ​​każdy programista może zdecydować, w jaki sposób chce to połączenie wydarzyć się. Chociaż Magento oferuje do tego niektóre klasy giełdowe, nawet w podstawowym kodzie użycie tych klas jest niespójne.

Alan Storm
źródło