Переосмислити абстрактний клас у Magento 2


13

У Magento 1 я міг скопіювати абстрактний клас у локальний або спільний каталог, і Magento використовував його, коли він автоматично завантажував цей клас.

Чи є якесь рішення зробити, щоб Magento замість цього завантажував мій клас vendor/magento/framework/Model/AbstractModel.php?

Налаштування di.xmlдля абстрактних занять не працює. Тільки плагіни?

Відповіді:


9

Тільки плагіни?

Так. Ви можете писати плагіни для абстрактних класів, а плагіни завжди мають перевагу над уподобаннями, якщо це можливо.

Налаштування корисні, якщо ви хочете замінити реалізацію. Я не можу придумати випадок використання для заміни реалізації для всіх моделей, що розширюються AbstractModel, якщо це навіть логічно можливо. Тому, напевно, ви хочете, щоб додати або змінити функціональність, і саме для цього потрібні плагіни.


1
Привіт, як я можу в цьому випадку замінити захищену функцію від абстрактного класу? ви можете допомогти
Манашві Бірла

2
Це неможливо. Найкраще - спробувати знайти спосіб додавання плагінів до загальнодоступних методів, які використовують захищений метод, і змінити поведінку таким чином, навіть якщо це передбачає більше коду та деяке дублювання.
Фабіан Шменглер

1
"Я не можу придумати випадок використання для заміни реалізації для всіх моделей, що розширюють AbstractModel" У мене є такий випадок використання: у мене є платіжний модуль, який використовує абстрактний базовий клас для 4 контролерів, кожен з яких використовує метод від базової для перевірки відповідь від шлюзу платежів. Тепер відповідь змінилася, і мені доведеться змінити всі 3.
Теро Лахтінен

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
Брудний злом, але іноді це може бути корисно для цього. M1 вимагає вручну зміни в основних класах (тому скопіюйте у додаток / код / ​​локальний), якщо ви хочете, щоб PDF-рахунок-фактура виглядав інакше, я вважаю, що буде такий випадок, коли це буде потрібно.
Зефірин

5

Якщо абстрактний клас має будь-який загальнодоступний або захищений метод, який ви хочете змінити, існує реальна можливість, якщо ви не можете використовувати додатки

Мені довелося перекрити метод _processDownloadвсередині \Magento\Downloadable\Controller\Download, додавши всередину 'if-s'. (Якщо хтось має уявлення, як я можу додати щось подібне до внутрішнього методу за допомогою плагінів, я буду вдячний). Клас абстрактний, тому перевагу не працювало. Плагіни також як захищений метод. Що я повинен був зробити, це переосмислити весь клас Download, використовуючи перевагу. Ці класи:

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

А всередині них перепишіть метод із батьківського класу (той, який я мав переосмислити). Тож фактично код перекритих методів був скопійований у три місця і був абсолютно однаковий.

Це не ідеально, але, працює.


4

Ви можете спробувати використати Magento Plugin для покращення існуючої функціональності будь-якого класу Анотація, хоча сфера функції повинна бути загальнодоступною. Нещодавно я працював над тим самим питанням, коли мені потрібно виключити продукти зі спеціальним атрибутом, присвоєними зі списку нещодавно переглянутих товарів .

Я використовував плагін для функції з назвою getItemsCollection з класу з іменем Magento \ Reports \ Block \ Product \ AbstractProduct, використовуючи наступний синтаксис:

файл: додаток \ код \ Пакет \ Модуль \ тощо \ frontend \ di.xml

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

файл: додаток \ код \ Пакет \ Модуль \ Блок \ Переглянуті.php

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

Ви можете використовувати як навколо, так і перед плагінами. Сподіваюся, ця робота для вас.


1
Я отримав успіх з вищевказаним кодом в одній з моїх вимог, насправді я хотів змінити деякі функції методу абстрактного класу модуля електронної пошти, і плагін допоміг мені досягти цього, дякую
bhargav shastri
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.