21

Like this thread said: Override abstract class in Magento 2 in Magento 1,

I can just create a fully new class. In Magento 2, we need to use plugins, but plugins only allow me to modify existing methods. What do I have to do if I want to add a new method?

Example:

This class vendor/magento/module-ui/Component/AbstractComponent.php, has an array of components: $components, there is no function to unset/delete elements for that array. So how can I create that function?

1
  • You cannot modify any class unless you update the source code. At the same time, you should not want it. So probably the assumption that modification of abstract class is a solution for some of your issues should be reviewed, and instead, you ask the initial thing you need to bedone
    – KAndy
    Commented Jun 22, 2022 at 17:43

6 Answers 6

1

overloading a class in M1 in the autoloader via community or local directory (like suggested in the question you linked) was considered bad practice in M1 for very good reasons.

Mostly you lose the ability to upgrade your Magento instance if the original class is changed in places, you did not consider in your overloaded class.

Actually, I cannot think of any use case, where you really need to add methods to an abstract class, since you always can add your own logic to an own class and integrate it in a plugin/observer/ViewModel/XML config

The best way would be, introduce a new class that extends the abstract class for your specific use case and then use your class where needed.

If you need to remove elements from a Ui Component, there is also likely a better way to do it via layout / a plugin on the layout processor / changing the js file that requires it.

So if you describe your specific use case there might be a better answer to this.

5
  • I know, that doing that is a bad practice, but at least, you have one way to do it. For instance, consider the case you want to add a cache for every single model you load. This could be done by modifying the load method in the abstract class and then this change will be propagated to all the classes. If you don't have this you have to modify each model you have, and that's absolutely not scalable at all.
    – Matias
    Commented Jan 29, 2019 at 21:56
  • A second use case, could be if you want to do what I say in the ticket, unset/delete elements from that array (consider as an example), you can think on whatever other thing... you need to create a new function in the abstract class, otherwise, you will be forced to create the same function in each class that extends, and that again is not scalable at all... And worst, because variables in Magento core are private instead of being protected, so the only way to do it is to add a method in the abstract class...
    – Matias
    Commented Jan 29, 2019 at 21:56
  • the first example is absolutely easy by just adding an around plugin to the abstract model and cache the result of load per model. Which would be much better then overloading the abstract class which would break every future update where the abstract model is changed. You second "example" I cannot tell you much about, because your basically asking exactly for adding a method to the abstract class, instead of stating your actual use case Commented Jan 30, 2019 at 5:37
  • btw it's still possible in Magento2 because you can manipulate the composer autoloader, but highly discouraged because you will have problems with updates magento.stackexchange.com/questions/164455/… Commented Jan 30, 2019 at 5:40
  • That´s not an option
    – Matias
    Commented Jan 30, 2019 at 18:40
0

I don't see how you can do that without completely overriding the class. In the case of your example, you can disable individual components by setting the "disabled" item to the "data" argument in the XML. For instance:

<?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>

This effectively removes 'title' from the $components array.

This is due to the createChildComponent method in the Magento\Framework\View\Element\UiComponentFactory class:

 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);
    }
3
  • This is not what I'm looking for... I want a way to add new methods to an Abstract class... this is just an example... for example, what if I want to remove the elements dynamically? In your comment you mention "complete overriding" how you do that??
    – Matias
    Commented Aug 23, 2016 at 20:48
  • Then you'll need to define your new methods in a class that extends the abstract class and then create classes for the abstract class's subclasses that instead inherit from your class and set preferences in di.xml. That's what I mean by 'completely overriding the class.' I was trying to show an example of how to avoid doing that. Commented Aug 23, 2016 at 21:05
  • Yes, I understand you... but the solution is not scalable at all... I cannot believe that M2 removed the possibility of overriding abstract classes... I thought that they were going to improve it, instead of removing it...
    – Matias
    Commented Aug 24, 2016 at 12:25
0

You can create a new class and extend the magento/module-ui/Component/AbstractComponent class

use Magento\Ui\Component\AbstractComponent;

class YourNewClass extends AbstractComponent
{
...

https://www.php.net/manual/en/language.oop5.abstract.php

0

How about writing a plugin on the getChildComponents function and putting your logic? It is not something we'd want to do of course, but it does seem the closest match to take over the property component in this abstract class.

-1

You can use class preference ,using before, around and after in the required method . Please check the docs for further details http://devdocs.magento.com/guides/v2.1/extension-dev-guide/plugins.html

-1

You have not found the correct Component class. The abstract class cannot be overridden and cannot add methods. The abstract class must have inherited classes. Find the class with the current function and rewrite it.

1
  • This is not correct... Imagine you wanna add a new method for all the models across Magento... there is not way to do it... I mean, you can manually override every single model to extend from your new class, but does not scale...
    – Matias
    Commented Oct 1, 2020 at 23:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.