Додавання нового методу до абстрактного класу в Magento 2


16

Як сказано у цій темі: Замініть абстрактний клас у Magento 2 у Magento 1 ,

Я просто можу створити абсолютно новий клас. У Magento 2 нам потрібно використовувати плагіни, але плагіни дозволяють мені змінювати існуючі методи. Що мені робити, якщо я хочу додати новий метод?

Приклад:

Цей клас vendor/magento/module-ui/Component/AbstractComponent.phpмає масив компонентів:, $componentsнемає функції для скидання / видалення елементів для цього масиву. Тож як я можу створити цю функцію?

Відповіді:


0

Я не бачу, як ви можете це зробити, не переставляючи класу повністю. У випадку вашого прикладу ви можете відключити окремі компоненти, встановивши елемент "вимкнено" на аргумент "дані" в XML. Наприклад:

<?xml version="1.0" encoding="UTF-8"?>

<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <fieldset name="general">
        <field name="title">
            <argument name="data" xsi:type="array">
                <item name="disabled" xsi:type="boolean">true</item>
            </argument>
        </field>
    </fieldset>
</form>

Це ефективно видаляє 'title' з $componentsмасиву.

Це пов’язано з createChildComponentметодом у Magento\Framework\View\Element\UiComponentFactoryкласі:

 protected function createChildComponent(
        array $bundleComponents,
        ContextInterface $renderContext,
        $identifier
    ) {
        list($className, $arguments) = $this->argumentsResolver($identifier, $bundleComponents);
        if (isset($arguments['data']['disabled']) && (int)$arguments['data']['disabled']) {
            return null;
        }
        $components = [];
        foreach ($bundleComponents['children'] as $childrenIdentifier => $childrenData) {
            $children = $this->createChildComponent(
                $childrenData,
                $renderContext,
                $childrenIdentifier
            );
            $components[$childrenIdentifier] = $children;
        }
        $components = array_filter($components);
        $arguments['components'] = $components;
        if (!isset($arguments['context'])) {
            $arguments['context'] = $renderContext;
        }

        return $this->objectManager->create($className, $arguments);
    }

Це не те, що я шукаю ... Я хочу, щоб додати нові методи до класу "Анотація" ... це лише приклад ... наприклад, що робити, якщо я хочу динамічно видаляти елементи? У своєму коментарі ви згадуєте "повне переосмислення", як ви це робите ??
Matias

Тоді вам потрібно буде визначити свої нові методи у класі, який розширює абстрактний клас, а потім створити класи для підкласів абстрактного класу, які замість цього успадковуватимуть від вашого класу та встановити налаштування у di.xml. Це я маю на увазі під "повністю перекриттям класу". Я намагався показати приклад, як уникнути цього.
Аарон Аллен

Так, я вас розумію ... але рішення взагалі не є масштабним ... Я не можу повірити, що M2 усунув можливість перекриття абстрактних класів ... Я подумав, що вони збираються його вдосконалити, а не видаляти .. .
Матіас


0

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

Переважно ви втрачаєте можливість оновити свій екземпляр Magento, якщо місцями змінюється початковий клас, ви не вважали його перевантаженим класом.

Насправді я не можу придумати жодного шаблону, де вам дійсно потрібно додати методи до абстрактного класу, оскільки ви завжди можете додати свою власну логіку до власного класу та інтегрувати її у конфігурацію плагіна / спостерігача / viewModel / xml

Найкращим способом було б введення нового класу, який розширює абстрактний клас для вашого конкретного випадку використання, а потім використовувати свій клас там, де потрібно.

Якщо вам потрібно видалити елементи з компонента інтерфейсу, також, ймовірно, кращий спосіб зробити це за допомогою макета / плагіна на процесорі компонування / зміни файла js, який цього вимагає.

Отже, якщо ви опишете свою конкретну скриньку, може бути кращою відповіддю на це.


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

Другий випадок використання може бути, якщо ви хочете виконати те, що я кажу в квитку, скасувати / видалити елементи з цього масиву (розгляньте як приклад), ви можете подумати над будь-якою іншою справою ... вам потрібно створити нову функцію в абстрактному класі, в іншому випадку, ви будете змушені створювати ту саму функцію в кожному класі, який розширюється, і це знову-таки зовсім не масштабується ... І найгірше, тому що змінні в ядрі Magento є приватними, а не захищеними, тому Єдиний спосіб зробити це - додати метод до абстрактного класу ...
Matias

перший приклад абсолютно простий, просто додавши плагін навколо абстрактної моделі та кешуючи результат завантаження на модель. Що було б набагато краще, ніж перевантажувати абстрактний клас, який би порушив кожне майбутнє оновлення, де змінюється абстрактна модель. Ви другий "приклад", я не можу вам сказати багато про що, оскільки ви в основному запитуєте саме про те, щоб додати метод до абстрактного класу, замість того, щоб
вказати

btw, це все ще можливо в Magento2, тому що ви можете маніпулювати композитором автозавантажувачем, але сильно відсторонено, тому що у вас будуть проблеми з оновленнями magento.stackexchange.com/questions/164455/…
Девід Верхолен

Це не варіант
Matias
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.