Answers:
仅插件?
是。您可以为抽象类编写插件,并且如果可能的话,始终应优先选择插件。
如果要替换实现,则首选项很有用。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
然后在它们内部重写父类的方法(我应该重写该方法)。因此,实际上重写方法的代码被复制到三个位置,并且完全相同。
这不是理想的方法,但是可行。
您可以尝试使用Magento插件来增强任何Abstract类的现有功能,尽管该功能的范围应为Public。最近,我处理同一问题,需要从“ 最近查看的产品”列表中排除分配了自定义属性的产品。
我使用以下语法从名为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;
}
您也可以在插件前后使用。希望这项工作对您有用。