Instanziieren von Helfern in Magento 2

26

Die neuesten Builds von Magento 2 haben die MageKlasse abgeschafft . Das heißt, wir haben die Mage::helperMethode verloren.

Gibt es eine Ersatztechnik (Helferfactory?) Zum Instanziieren von Helfern in Magento 2? Oder es wird erwartet, dass wir die neue Object Manager-Klasse verwenden und den Helfer einfach als Singleton / Cache-Objekt mit get(vs. create) instanziieren.

Alan Storm
quelle

Antworten:

31

Ich sehe, du bist zur richtigen Lösung gekommen, willst nur zusammenfassen.

Die Konstruktorinjektion sollte verwendet werden, um Helfer (oder eine andere Instanz) in der von Ihnen benötigten Klasse abzurufen:

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

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

Beachten Sie, dass keine phpDoc-Kommentare erforderlich sind. Magento liest die Konstruktorsignatur direkt, um herauszufinden, welche Abhängigkeiten erforderlich sind.

\ Magento \ Core \ Helper \ Factory sollte nur in den seltenen Fällen verwendet werden, wenn Sie mehrere Helfer anrufen müssen oder nicht genau wissen, welche Sie benötigen.

Von der direkten Verwendung von Object Manager wird strengstens abgeraten . Also bitte vermeiden Sie:

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

Es dient nur zur Serialisierung / Deserialisierung.

Anton Kril
quelle
Verwenden Sie kein Static, da es nicht mit PHP getestet werden kann und ja, davon wird abgeraten. Alle M2-Abhängigkeiten werden über den Konstruktor ausgeführt und vom Objekt-Manager intern verwaltet. Sie werden als Singleton abgerufen. Verwenden Sie auch nicht _, um eine Eigenschaftssichtbarkeit anzugeben. Alle M2-Namen sollten den Camecase verwenden
PartySoft
@ Anton Kril Wenn wir helperin Vorlage verwenden, wie $this->helper('Magento\Catalog\Helper\Image')folgt es der Best Practice?
Khoa TruongDinh
2
Nein, tut es nicht. Vorlagen sollten nur auf Blöcke verweisen. Helfer sollten vermieden werden
Anton Kril
10

Es sieht so aus, als würden Magentos ermutigende Leute ihr neues automatisches Abhängigkeitsinjektionssystem verwenden, um Helfer und Modelle über den Konstruktor des Objekts in Objekte zu bringen.

Die kurze Version? Wenn Sie ein Objekt, das von dem Objektmanager instanziiert ist, und einen Konstruktor mit einem PHPDoc dekorieren@param , und die Parameter hat einen richtigen Typ Hinweis gesetzt, wird der Objektmanager instanziiert automatisch den Helfer (oder, wie ich glaube, andere Objekte) für Sie.

Der folgende Konstruktor würde beispielsweise einen Core Data Helper in das Objekt einfügen.

/**
* @param \Magento\Core\Helper\Data $coreData
*/        
public function __construct(\Magento\Core\Helper\Data $coreData)
{
    $this->_coreHelper = $coreData;            
}
Alan Storm
quelle
Dies ist die richtige Antwort - gutes Schlafen; war mir auch nach langem Graben nicht ganz klar.
Philwinkle
2
OK ... jetzt tut mir der Kopf ... sehr weh. Sie meinen, dass wir PHPDoc verwenden sollen, um Code zu "schreiben"? Das ist Wahnsinn. Ich gebe auf.
Marius
@Marius hahaha das ist nicht ungewöhnlich - Alans Blog erklärt es in gewissem Maße.
Philwinkle
3
@philwinkle. Ich habe seinen Artikel gelesen. Sehr interessant, aber ich sage immer noch, das ist Wahnsinn. Nennen Sie mich altmodisch, aber "in meinen Tagen" Code war Code und Kommentare waren die Dinge, die fast niemand zu schreiben hat.
Marius
Oh ... und übrigens. +1. Gute Frage & nette Antwort.
Marius
7

Abgesehen von den obigen Antworten können Sie, wenn Sie den Helfer in der HTML-Vorlage verwenden müssen, einfach so vorgehen:

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

Ich hoffe es ist hilfreich wenn jemand es vorher nicht gewusst hat;)

rbncha
quelle
6

Die Art und Weise, wie Helfer instanziiert werden (zumindest für das neue Backend (~ dev50) -Modul), erfolgt über eine helperFactory:

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

Das ist im Wesentlichen nur ein spezialisierter Typ einer Modellfabrik. Beispiel: Magento \ Core \ Block \ Context-Zeile 143 (dev50) als Teil des Konstruktors:

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

Die Helfer-Factory gibt das angeforderte Modell basierend auf dem Klassennamen zurück und stellt sicher, dass es sich um eine instanceofabstrakte Helfer-Klasse handelt:

/**
 * 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;
}

Wenn Sie dies selbst implementieren , scheint es, als würde Magento Core es auf zwei Arten laden:

Rollen Sie Ihre eigene Fabrik:

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

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

Oder greifen Sie einfach direkt zu:

$helper = \Magento\Core\Model\ObjectManager::getInstance()->get('Magento\Core\Helper\Data');
Philwinkle
quelle
1
+1 für nützliche Informationen, aber möchten Sie die Factory direkt so instanziieren? Oder sollte eine einzelne Helfer-Factory mit dem Objekt-Manager als zwischengespeicherte Klasse mit instanziiert werden get?
Alan Storm
Es ist nicht ganz klar, da die Helferfabrik von \ Mage \ Core \ Block \ Abstract geerbt wurde. Ich denke, es ist Ihre Absicht, Ihre eigene Helferfabrik bereitzustellen. Es sieht jedoch nicht so aus, als würden sie absichtlich einen Singleton für die Fabrik erstellen.
Philwinkle
Klingt so, als ob ich es brauche / die beste Quelle ist, zu verfolgen, wie _helperFactory in diese Objekte injiziert wird, und zu sehen, wie das Kernteam es instanziiert.
Alan Storm
Meine Zusammenfassung der Vereinfachung ist falsch, und der Konstruktor benötigt eine Instanz von ObjectManager. Ich werde es gleich bearbeiten.
Philwinkle
Siehe Bearbeiten. Es sollte funktionieren - schwer zu bestimmen, da meine Cli-Shell-Umgebung die Store-Konfigurationsinstanz nicht erwartungsgemäß lädt. Dies sollte jedoch ausreichen, um Sie auf den richtigen Weg zu bringen.
Philwinkle
0

Versuchen Sie es auf diese Weise

$helper = \Magento\Framework\App\ObjectManager::getInstance()->get('Xx\Xx\Helper\Xx');
Thushan
quelle
Von der direkten Verwendung von Object Manager wird strengstens abgeraten.
Sv3n
@sv3n könntest du bitte erklären, woran das liegt ?. Vielen Dank.
Thushan
1
Verwenden Sie stattdessen lieber Abhängigkeitsinjektionen ... hier beantwortet zum Beispiel ... magento.stackexchange.com/questions/142352/…
sv3n