Magento 2ヘルパーインスタンス


11

Magento 2のDIシステムに頭を巻きつけたと思うと、何かが出てきて、包みを解きます。
ヘルパーにアクセスするさまざまな方法をコアコードで確認します。
たとえば、Magento\Catalog\Controller\Category::_initCategoryこれがあります:

if (!$this->_objectManager->get('Magento\Catalog\Helper\Category')->canShow($category)) {
    return false;
}

しかしMagento\Catalog\Block\Category\View、ヘルパーではコンストラクタに注入されます

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Catalog\Model\Layer\Category $catalogLayer,
    \Magento\Framework\Registry $registry,
    \Magento\Catalog\Helper\Category $categoryHelper,
    array $data = array()
) {
    $this->_categoryHelper = $categoryHelper;
    $this->_catalogLayer = $catalogLayer;
    $this->_coreRegistry = $registry;
    parent::__construct($context, $data);
}

これにより、コントローラーとブロック(およびモデル)ではヘルパーに異なる方法でアクセスする必要があると思いましたが、ヘルパーがコンストラクターに挿入されているコントローラーを見つけましたMagento\Catalog\Controller\Adminhtml\Product\Action\Attribute

霧を取り除いてください。
いつDIを使用する必要がありますobjectManagerか?なぜ?
私はこの質問を読みました:Magento 2でのヘルパーのインスタンス化。これはそれに関するフォローアップの質問です。

回答:


10

オブジェクトマネージャを使用することはすでにデメテルの法則に違反しているため、可能な限りDIを使用することをお勧めします。オブジェクトマネージャを使用する場合、これらの依存関係はメソッドロジックで非表示になるだけです。


うん。同意する。DIを使用しますが、これがコアで行われる理由に興味がありますか?たぶん、誰かが私が言及したクラスをリファクタリングできなかったのでしょうか?
マリウス

Afaik彼らはまだ多くのリファクタリングを行っており、これらの場所にも触れてくれることを期待しています。しかし、ある時点で実際にリリースしたい場合に存在しなければならない優先順位についても知らない。したがって、多分いくつかの新機能や他の悪い習慣が最初に修正されるでしょう。
トビアス

10個の関数のクラスがあり、1個の関数だけが特定のモデルを必要とする場合はどうなりますか?オブジェクトマネージャーを使用して1つの単一の関数内のみでモデルを読み込むことができる一方で、10の各関数のコンストラクターインジェクションを介してモデルを読み込むのに(パフォーマンスビューから)冗長ではないでしょうか。
JohnyFree

6

Magentoの実装についてはあまり知りませんが、これObjectManagerService Locatorのようです。

一般に、Service Locatorを使用してオブジェクトの依存関係にアクセスするのはかなり悪いです。この記事をチェックしてください

コンストラクタを介して依存関係を明示的に定義する方がはるかに優れたアプローチです。定義されていないサービスの単体テストと実行時の問題に役立ちます。

オブジェクトマネージャーをクラスに注入することは、基本的に、すべてのアプリケーションサービスにアクセスできるクラスにレジストリを注入することですが、これは明らかに正しくありません。

私が使用しZF2に公平なビットを、一般的に、依存関係を必要とするサービス、コントローラおよび任意のクラスのための小さな工場のクラスを定義します。これらのファクトリクラスはサービスロケータにアクセスし、オブジェクトが依存するすべてのサービスを取得し、コンストラクタを通じてそれらを注入します。それは主に、何かのコードを捨てているようファクトリクラスのサービスロケータを使用することは結構です、この例を。

これらの工場はまだテストが簡単です。

IMO、可能な限りコンストラクター注入を使用します。繰り返しますが、私はMagentoの実装についてあまり詳しくありません。ファクトリーの概念がある場合、一見するとそれらをサポートしているように見えますが、クラスを明示的に定義し、Service Locatorを使用してそれらをFactoryクラスで構築することはよりクリーンなアプローチ。

これは上記のパターンへの露出が限られている人からのものですので、この件に関する他の人の考えや経験も聞きたいです!

もっと読む


素敵な説明をありがとう。私の質問は、「コアのヘルパーにアクセスする2つの方法があるのはなぜですか?」これは少し話題から外れていますが、私が抱いていた他のいくつかの疑問は解消されました。:)ありがとう。
マリウス

おそらく、まだリファクタリングされていないものだと思います。それか、それとも使いやすさかもしれません。特にRADを実行する場合、すべての依存関係を常にコントローラーに注入するようコンシューマーに要求することは、逆効果と見なされる可能性があります。依存関係にアクセスするための両方の方法をコンシューマーに与えると、RADアプローチが可能になりますが、必要に応じて他のユーザーが依存関係を明示的に定義できるようになります。
アイディンハッサン

5

(テンプレートで)ヘルパーを使用するもう1つの方法は次のとおりです。

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

まだご存じない方にもお役に立てれば幸いです。


これは、オブジェクトマネージャーの使用に似ています。それが最良のアイデアかどうかはわかりません。
マリウス

1
上記の方法は、私が知る限り、テンプレートにのみ適用されます。オブジェクトマネージャは、コントローラ、ブロック、モデルで使用されているなど
rbncha

1
テンプレートにコードの依存関係がないため、コードと同じ球場にはありません。テンプレートは単なるコンシューマーであり、カプセル化が壊れているクライアントを汚染することはありません。
デモンコリュー2017

デモコリュが何を言おうとしているのか、私にはわかりません。しかし、モジュールのヘルパーを呼び出す最良の方法はこれです。これはマジェントです。彼らが言うように、すべてのブロック/セクションコードはコアに触れることなく呼び出し可能/変更可能であることを意図しています。したがって、すべてが相互に関連しているか、依存関係があります。
rbncha 2018年

2

それは古い質問ですが、私がいるかどうかわからないんだけどマリウスはその答えを得ました。マリウスはもっとよく答えられると思います。一言でお答えしたいと思います。Magento 2がヘルパーの代わりにDIの使用を提案するのはなぜですか?

  • 単体テストでの分離を可能/簡単にする
  • クラスの依存関係を明示的に定義する
  • 優れた設計の促進(単一責任原則(SRP)など)
  • モジュールでDIを使用すると、Magentoがこれらのインターフェースの基本的な実装を変更した場合の非互換性バグのリスクが軽減されます。これは、拡張機能の開発者が理解する重要な概念です。

M2コアがDIを使用しない場合があるのはなぜですか?

  • クラス数の減少
  • 不要なインターフェースを作成しない
  • 非互換性バグのリスクなし

コアカタログモジュールはヘルパーとして使用されていますが、DIを幅広く使用しています。私の調査では、Magento 2がコアカタログヘルパーファイルのサービス契約に適さない機能をいくつか使用していることがわかりました。

Magento定義のクラス(\ Magento \ Catalog \ Model \ Productなど)を明示的に使用する必要がある場合は、サービスコントラクトインターフェイスではなく具体的​​な実装に応じて、暗黙的な依存関係を明示的に指定します。

間違いなく、拡張機能の開発者はヘルパーのようなMagento1の代わりにDIを使用する必要があります。Magento 2のガイドラインに従って実装すると、フォールアウトが制限されます。推奨事項を破ると、問題が発生します。


ええ、その間私は私の答えを得ました。しかし、時間を割いて答えてくれてありがとう。これは、このオンラインで検索する人々にとって貴重な情報です。
マリウス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.