Tworzenie wystąpień Pomocników w Magento 2

26

Najnowsze wersje Magento 2 wyeliminowały Mageklasę. To oznacza, że ​​zgubiliśmy Mage::helpermetodę.

Czy istnieje technika zastępcza (fabryka pomocników?) Do tworzenia instancji pomocników w Magento 2? Czy też powinniśmy używać nowej klasy Object manager i po prostu tworzyć instancję pomocnika jako obiekt singleton / buforowany za pomocą get(vs. create)

Alan Storm
źródło

Odpowiedzi:

31

Widzę, że znalazłeś właściwe rozwiązanie, chcę tylko podsumować.

Wstrzyknięcie konstruktora powinno być użyte do odzyskania pomocnika (lub dowolnej innej instancji) w dowolnej klasie:

class SomeClass
{
    public function __construct(\Magento\Core\Helper\Data $helper)
    {
        $this->helper = $helper;
    }

    public function doSmth()
    {
        $this->helper->someMethod();
    }
}

Zauważ, że nie są wymagane żadne komentarze phpDoc , Magento odczyta podpis konstruktora bezpośrednio, aby dowiedzieć się, jakie zależności są wymagane.

\ Magento \ Core \ Helper \ Factory powinien być używany tylko w tych rzadkich przypadkach, gdy trzeba wezwać wielu pomocników lub nie wiesz dokładnie, którego potrzebujesz.

Bezpośrednie korzystanie z Object Managera nie jest zalecane . Dlatego unikaj używania:

\Magento\Core\Model\ObjectManager::getInstance()

Jest tam tylko do serializacji / deserializacji.

Anton Kril
źródło
nie używaj statycznego, ponieważ nie można go przetestować za pomocą jednostki PHP i tak, jest to odradzane. Wszystkie zależności M2 są wykonywane przez konstruktor i są zarządzane wewnętrznie przez Object Managera i będą pobierać je jako Singleton. Nie używaj też _ do wskazania widoczności właściwości, wszystkie nazewnictwo M2 powinno używać kamery
PartySoft
@Anton Kril, jeśli używamy helperw szablonie, na przykład $this->helper('Magento\Catalog\Helper\Image'), postępuje zgodnie z najlepszą praktyką?
Khoa TruongDinh
2
Nie. Szablony powinny odnosić się tylko do bloków. Pomocników należy unikać
Anton Kril,
10

Wygląda na to, że Magento zachęca ludzi do korzystania z nowego systemu automatycznego wstrzykiwania zależności , aby wprowadzać pomocników i modele w obiekty za pomocą konstruktora obiektu.

Krótka wersja? Jeśli masz obiekt utworzony przez menedżera obiektów i udekorujesz konstruktor za pomocą PHPDoc@param , a parametry mają odpowiedni zestaw wskazówek typu, menedżer obiektów automatycznie utworzy dla ciebie pomocnika (lub, jak sądzę, inne obiekty).

Na przykład następujący konstruktor wstrzykuje pomocniczy klucz danych do obiektu.

/**
* @param \Magento\Core\Helper\Data $coreData
*/        
public function __construct(\Magento\Core\Helper\Data $coreData)
{
    $this->_coreHelper = $coreData;            
}
Alan Storm
źródło
To jest poprawna odpowiedź - świetny sen; nie było dla mnie całkowicie oczywiste, nawet po wielu kopaniach.
philwinkle,
2
OK ... teraz boli mnie głowa ... bardzo. Masz na myśli, że mamy używać PHPDoc do „pisania” kodu? To szaleństwo. Wychodzę.
Marius
@Marius hahaha to nie jest takie rzadkie - blog Alana do pewnego stopnia to wyjaśnia.
philwinkle,
3
@philwinkle. Przeczytałem jego artykuł. Bardzo interesujące, ale wciąż mówię, że to szaleństwo. Nazywaj mnie staroświeckim, ale kod „za moich czasów” był kodem, a komentarze były tymi rzeczami, o których prawie nikt nie pisał.
Marius
Och ... a tak przy okazji. +1. Dobre pytanie i miła odpowiedź.
Marius
7

Oprócz wszystkich powyższych odpowiedzi, jeśli musisz użyć pomocnika w szablonie phtml, możesz po prostu zrobić tak:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]');

Mam nadzieję, że to pomocne, jeśli ktoś wcześniej tego nie wiedział;)

rbncha
źródło
6

Sposób tworzenia instancji helperów (przynajmniej dla nowego modułu Backend (~ dev50)) odbywa się za pośrednictwem helperFactory:

/**
 * Return helper object
 *
 * @param string $name
 * @return \Magento\Core\Helper\AbstractHelper
 */
public function helper($name)
{
    return $this->_helperFactory->get($name);
}

Co jest w zasadzie tylko wyspecjalizowanym typem fabryki modeli. Np .: Magento \ Core \ Block \ Context line 143 (dev50) jako część konstruktora:

\Magento\Core\Model\Factory\Helper $helperFactory

Fabryka pomocników zwróci żądany model na podstawie nazwy klasy i zapewni, że jest to instanceofklasa abstrakcyjna pomocnika:

/**
 * Get helper singleton
 *
 * @param string $className
 * @param array $arguments
 * @return \Magento\Core\Helper\AbstractHelper
 * @throws \LogicException
 */
public function get($className, array $arguments = array())
{
    $className = str_replace('_', '\\', $className);
    /* Default helper class for a module */
    if (strpos($className, '\Helper\\') === false) {
        $className .= '\Helper\Data';
    }

    $helper = $this->_objectManager->get($className, $arguments);

    if (false === ($helper instanceof \Magento\Core\Helper\AbstractHelper)) {
        throw new \LogicException(
            $className . ' doesn\'t extends Magento\App\Helper'
        );
    }

    return $helper;
}

Gdybyś sam to zaimplementował , wygląda na to, że rdzeń Magento ładuje go na jeden z dwóch sposobów:

Rzuć własną fabrykę:

$objectManager = \Magento\Core\Model\ObjectManager::getInstance();

$helperFactory = $objectManager->get('\Magento\Core\Model\Factory\Helper');
$helper = $helperFactory->get('\PulseStorm\Commercebug\Helper\Data');

Lub po prostu złap go bezpośrednio:

$helper = \Magento\Core\Model\ObjectManager::getInstance()->get('Magento\Core\Helper\Data');
philwinkle
źródło
1
+1 za przydatne informacje, ale czy chcesz bezpośrednio utworzyć instancję fabryki? Czy może powinna zostać utworzona instancja jednej fabryki pomocników z Menedżerem obiektów jako klasa buforowana get?
Alan Storm
Nie jest do końca jasne, ponieważ fabryka pomocników jest dziedziczona z \ Mage \ Core \ Block \ Abstract - Myślę, że intencją jest zapewnienie własnej fabryki pomocników. Nie wygląda jednak na to, żeby celowo tworzyli singleton dla fabryki.
philwinkle,
Wygląda na to, że potrzebuję / najlepszym źródłem jest prześledzenie, w jaki sposób _helperFactory jest wstrzykiwany do tych obiektów i zobaczenie, jak tworzy go instancja zespołu podstawowego.
Alan Storm
Moje streszczenie uproszczenia jest nieprawidłowe, a konstruktor wymaga wystąpienia obiektu ObjectManager. Będę edytować za chwilę.
philwinkle,
Zobacz edycję. Powinno to działać - trudne do ustalenia w tym momencie, ponieważ moje środowisko cli shell nie ładuje instancji konfiguracji sklepu zgodnie z oczekiwaniami. To powinno wystarczyć, abyś znalazł się na właściwej drodze.
philwinkle,
0

Wypróbuj w ten sposób

$helper = \Magento\Framework\App\ObjectManager::getInstance()->get('Xx\Xx\Helper\Xx');
Tuszan
źródło
Bezpośrednie korzystanie z Object Managera nie jest zalecane.
sv3n
@ sv3n czy mógłbyś wyjaśnić, jaki jest powód ?. Dzięki.
Thushan
1
Lepsze użycie zastrzyków uzależnienia zamiast ... odpowiedział tutaj na przykład ... magento.stackexchange.com/questions/142352/…
sv3n