回答:
プラグインのみ?
はい。抽象クラス用のプラグインを作成できます。可能な場合、プリファレンスよりもプラグインを常に優先する必要があります。
設定は、実装を置き換える場合に役立ちます。AbstractModel
論理的に可能であれば、拡張するすべてのモデルの実装を置き換えるユースケースを考えることはできません。おそらくあなたが望むのは、機能を追加または変更することであり、これがプラグインの目的です。
完全なソリューション:magentoが自動ロードする前に、置き換えられたクラスを含めます。だからステップバイステップ:
ファイルapp/etc/NonComposerComponentRegistration.php
に行を追加
$pathList[] = dirname(__DIR__) . '/etc/ClassReplacer.php';
コンテンツを含むイン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/');
app/code/Magento
置き換えられるクラスへの配置、例えばapp/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
抽象クラスに、オーバーライドするパブリックメソッドまたはプロテクトメソッドがある場合、実際にプラグインを使用できない場合の方法があります。
_processDownload
内部のメソッドをオーバーライドする必要があり\Magento\Downloadable\Controller\Download
、内部にいくつかの「if-s」を追加しました。(誰かがプラグインを使用してこの内部メソッドのようなものをどのように追加できるか考えているなら、私は感謝します)。クラスは抽象なので、設定は機能しませんでした。メソッドも保護されているため、プラグインも。私がしなければならなかったのはDownload
、プリファレンスを使用して、から拡張されるすべてのクラスをオーバーライドすることでした。これらのクラス:
Magento\Downloadable\Controller\Download\Link
Magento\Downloadable\Controller\Download\LinkSample
Magento\Downloadable\Controller\Download\Sample
そしてそれらの内部で、親クラス(私がオーバーライドすることになっていたもの)からメソッドを書き換えます。実際、オーバーライドされたメソッドのコードは3つの場所にコピーされ、まったく同じでした。
理想的ではありませんが、機能します。
関数のスコープは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;
}
プラグインの前と同様に使用できます。この仕事があなたのために願っています。