Magento 2 CRUD / Abstractモデルへの依存関係の注入


12

Magento 2 CRUDモデルに依存関係を挿入することはできますか?

つまり、Magento 2には基本抽象モデルクラスがありますMagento\Framework\Model\AbstractModel。単純なモデルオブジェクトの作成、読み取り、更新、削除を作成する場合は、このクラスを独自のクラスで拡張します。

class Foo extends Magento\Framework\Model\AbstractModel
{
}

モデルの__constructメソッドに依存関係を挿入することは可能ですか?しようとすると、次のエラーが発生します。

致命的なエラー:抽象クラスMagento \ Framework \ Model \ ResourceModel \ AbstractResourceをインスタンス化できません

犯人はAbstractModel__construct方法のようです。

public function __construct(
    \Magento\Framework\Model\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
    \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
    array $data = []
) {

このコンストラクターには Magentoオブジェクトマネージャーインターフェイスではない 2つのタイプヒントがあります(Magento\Framework\Model\ResourceModel\AbstractResourceMagento\Framework\Data\Collection\AbstractDb)。それらは抽象クラスです。このクラスを拡張し、注入された依存関係を追加しようとすると

class Foo extends Magento\Framework\Model\AbstractModel
{
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
        \Package\Module\Model\Mine $mine,

    ) {
        //...
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);

    }
}

オブジェクトマネージャが抽象クラスをインスタンス化しようとすると、Magentoがベイルします。

オブジェクトの依存関係を抽象クラスの前に移動することで、これを「修正」できます

    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,

        \Package\Module\Model\Mine $mine,

        \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = [],
    ) {  

ただし、これにより引数の順序が変更されました。完全にオブジェクト管理されたクラスでは、これは問題になりません。ただし、これらの抽象クラスのタイプヒントが存在するという事実は、手動で(つまり、オブジェクトマネージャーまたはDIを介さずに)CRUDオブジェクトをインスタンス化し、その特定の順序でタイプヒント適合するオブジェクトを渡すMagentoシステムの一部があることを意味します。

これは安全ですか?すなわち、抽象モデルのコンストラクタのこれらの抽象クラスは単なるレガシーコードであり、使用されていませんか?または、システムの一部はまだこれらを使用しますか?つまり、CRUDモデルに依存関係を注入することはできませんか?

回答:


9

まず第一に、コンストラクタはクラスのプライベートAPIです。コンストラクター関数は特別な意味を持ち、親クラスと同じ引数のリスト/順序を持つ必要はありません。

Magento 2 CRUDモデルに依存関係を挿入することはできますか?

はい、もちろん。

これは安全ですか?

はい。ただし、Magento Object Managerは、すべてのオプションパラメータがリストの最後に配置され、オプションパラメータの後に必須パラメータが解決されないと想定しています。

$ resource、$ resourceCollection引数はレガシーですが、Modelクラスで広く使用されています。モデルのほとんどは、このようなコードを使用してリソースとコレクションクラスを初期化します。

protected function _construct() { 
    $this->_init('Magento\AdminNotification\Model\Resource Model\Inbox'); 
}

これが、このパラメーターがオプションである理由です。しかし、たとえば、単体テストでは、コンストラクターでリソースまたはコレクションモックを渡して、置換を実現できるようにします。


@Kanday Magentoのエンジニアリング/アーキテクチャ部門は、コアクラスのコンストラクタの順序は無関係であるという公式声明を出しましたか?それとも、ほとんどの人がそれに取り組んでいるだけの希望ですか?
アランストーム

私はそれを「無関係」とは呼びません。OMだけが必要な引数をコンストラクタに渡し、親クラスの順序に依存しません。さらに、INはパラメーターの名前を使用するため、パラメーターを変更しない方がよい(
PHP

あなたが言っていることを理解しているかどうかはわかりません。将来のある時点で、Magentoシステムのコアコードが引数/パラメータの順序を再び重要なものとして扱い始める可能性があると言っていますか?
アランストーム

信じられない
KAndy

再度、感謝します!FWIW、そしてGoogle社員にとっては、これは安全なことのように思えます。私が言えることから、コンストラクターのパラメーターの順序を想定して、モデルを盲目的にインスタンス化するMagentoシステムコードはありません。
アランストーム

6

これは安全なようです。少なくとも、magentoはこれを多くの場所で行っています。例については、クラスの以下の(排他的ではない)リストの__constructメソッドを参照してください

  • \ Magento \ Theme \ Model \ Theme \ File
  • \ Magento \ Theme \ Model \ Design
  • \ Magento \ Sales \ Model \ Order \ Creditmemo

残念ながら、あなたの質問の他の部分には答えられません。


4
  1. モデルはどのように使用しますか?
  2. あなたの場合$mine必須パラメーターですが$resource$resourceCollection$dataオプションです。オプションのパラメーターは常に最後に配置する必要があります。そうでない場合、オプションのパラメーターを使用することはできません。したがって$mine、オプションのパラメータの前に指定する必要があることは、私には良さそうです。

これらの抽象パラメータを除いて、依存性が注入されたパラメータではなく、Magentoコアシステムコードがそこにあると予想される場合$mine、キューの先頭に移動するとエラーが発生します。Magentoコアシステムコードそれらを使用しない場合、なぜ存在するのですか?それが私が一番下に到達しようとしている質問です。パラメータを移動した状態でモデルを使用できるからといって、安全になりません。
アランストーム

一部のモデルでは、これらのオプションパラメータを使用してカスタムリソースモデルを渡すことができます。たとえば、github.com
magento

Magentoは反射を使用して、パラメーターがオプションかどうかを判断します。そして、PHPは、全てのパラメータが必要なパラメータの前に立って考えて必要。したがって、$mineオプションのパラメーターの前に移動すると、それらは本当にオプションになり、Magentoはデフォルト値(nullarray())を渡すだけです。必須パラメーターをオプションのパラメーターの後に配置すると、PHPはオプションのパラメーターを必須パラメーターと見なし、Magentoはそれらをインスタンス化しようとしました(ただし、それらの設定はありません)。
ブスカムザ

紛らわしいように思えますが、モデルクラス内で抽象クラスを処理するのではなく、抽象クラスの設定をセットアップすることもできます。そのため、実際のオブジェクトは常に注入されます。
ブスカムザ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.