Magento 2の抽象クラスをオーバーライドする


13

Magento 1では、抽象クラスをローカルディレクトリまたはコミュニティディレクトリにコピーすることができ、Magentoはこのクラスを自動ロードするときにそれを使用しました。

代わりにMagentoにクラスをロードする解決策はあり vendor/magento/framework/Model/AbstractModel.phpますか?

di.xml抽象クラスの設定は機能しません。プラグインのみ?

回答:


9

プラグインのみ?

はい。抽象クラス用のプラグインを作成できます。可能な場合、プリファレンスよりもプラグインを常に優先する必要があります。

設定は、実装を置き換える場合に役立ちます。AbstractModel論理的に可能であれば、拡張するすべてのモデルの実装を置き換えるユースケースを考えることはできません。おそらくあなたが望むのは、機能追加または変更することであり、これがプラグインの目的です。


1
こんにちは、この場合、抽象クラスから保護された関数をオーバーライドするにはどうすればよいですか?助けてください
マナシュヴィビルラ

2
それは可能ではありません。最良の方法は、保護されたメソッドを使用するパブリックメソッドにプラグインを追加する方法を見つけ、それがより多くのコードと重複を伴う場合でも、この方法で動作を変更することです。
ファビアンシュメングラー

1
「AbstractModelを拡張するすべてのモデルの実装を置き換えるユースケースを考えることはできません」私はそのようなユースケースがあります。支払いゲートウェイからの応答。さて、応答が変更されていると私はすべて3変更する必要があります
TERO Lahtinen

6

完全なソリューション:magentoが自動ロードする前に、置き換えられたクラスを含めます。だからステップバイステップ:

  1. ファイルapp/etc/NonComposerComponentRegistration.phpに行を追加

    $pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';
  2. コンテンツを含むインapp/etcプレースファイルClassReplacer.php

    class ClassReplacer
    {
        public function includeReplacedFiles($src)
        {
            try {
                $replacedFiles = $this->listDir($src, false, true);
                foreach ($replacedFiles as $replacedFile) {
                    include_once $src . $replacedFile;
                }
            } catch (Exception $e) {
                return;
            }
        }
    
        protected function listDir($dir, $prependDir = false, $recursive = false, $entityRegexp = null, $currPath = '')
        {
            if (!is_dir($dir)) {
                return array();
            }
            $currPath = $prependDir ? $dir : $currPath;
            $currPath = $currPath !== '' ? rtrim($currPath, '/') . '/' : '';
            $files = array();
            foreach (scandir($dir) as $file) {
                if (in_array($file, array('.', '..'))) {
                    continue;
                }
                $entity = $currPath . $file;
                if ($recursive && is_dir("$dir/$file")) {
                    $files = array_merge($files, $this->listDir("$dir/$file", false, true, $entityRegexp, $entity . '/'));
                    continue;
                }
                if ($entityRegexp && !preg_match($entityRegexp, $entity)) continue;
                $files[] = $entity;
            }
            return $files;
        }
    }
    $replace = new ClassReplacer();
    $replace->includeReplacedFiles(dirname(__DIR__) . '/code/Magento/');
  3. app/code/Magento置き換えられるクラスへの配置、例えばapp/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php



1
汚いハックですが、それができると便利な場合があります。請求書PDFの外観を変えたい場合は、M1でコアクラスを手動で変更する必要があるため(app / code / localにコピーします)、これが必要になる場合があります。
-Zefiryn

5

抽象クラスに、オーバーライドするパブリックメソッドまたはプロテクトメソッドがある場合、実際にプラグインを使用できない場合の方法があります。

_processDownload内部のメソッドをオーバーライドする必要があり\Magento\Downloadable\Controller\Download、内部にいくつかの「if-s」を追加しました。(誰かがプラグインを使用してこの内部メソッドのようなものをどのように追加できるか考えているなら、私は感謝します)。クラスは抽象なので、設定は機能しませんでした。メソッドも保護されているため、プラグインも。私がしなければならなかったのはDownload、プリファレンスを使用して、から拡張されるすべてのクラスをオーバーライドすることでした。これらのクラス:

Magento\Downloadable\Controller\Download\Link Magento\Downloadable\Controller\Download\LinkSample Magento\Downloadable\Controller\Download\Sample

そしてそれらの内部で、親クラス(私がオーバーライドすることになっていたもの)からメソッドを書き換えます。実際、オーバーライドされたメソッドのコードは3つの場所にコピーされ、まったく同じでした。

理想的ではありませんが、機能します。


4

関数のスコープはPublicである必要がありますが、Magentoプラグインを使用して、Abstractクラスの既存の機能を強化することができます。最近私は同じ問題に取り組み、カスタム属性が割り当てられた製品を「最近表示した製品」リストから除外する必要がありました。

次の構文を使用して、Magento \ Reports \ Block \ Product \ AbstractProductというクラスのgetItemsCollectionという関数のプラグインを使用しました。

ファイル:app \ code \ Package \ Module \ etc \ frontend \ di.xml

<type name="Magento\Reports\Block\Product\AbstractProduct">
    <plugin name="Package_Module::aroundGetItemsCollection" type="Package\Module\Block\Viewed" sortOrder="20"/>
</type>

ファイル:app \ code \ Package \ Module \ Block \ Viewed.php

public function afterGetItemsCollection(
    $subject, $result
) {
    $result = $result->addAttributeToFilter('skip_hire_product', [['neq' => 1], ['null' => true]], 'left');
    return $result;
}

プラグインの前と同様に使用できます。この仕事があなたのために願っています。


1
要件の1つで上記のコードで成功しました。実際、メールモジュールの抽象クラスメソッドの一部の機能を変更したかったので、プラグインでこれを達成できました。おかげで
bhargav shastri
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.