3

In Magento 2 for themes, it's incredibly easy to extend from a parent. This follows a nice logical hierarchy when inheriting theme .xml and .phtml files. This is clearly defined in the theme.xml.

However in my experience thus far with Magento 2. Modules by nature are (And understandably) entirely encapsulated with their respected module namespaces. Which in most cases, inherit from the Magento 2 Vendor core.

Although when wanting to inherit from a Third party module that may, or may not already extend from the Magento core. As I may have business specific functionality to add.

Say for example, the Third Party namespace and folder structure that extends the a Third Party's Blog:

  • /app/code/[ThirdPartyVendor]/[SimpleBlog]
    • /Block
      • ...
    • /Controller
      • /Post
        • Index.php

This SimpleBlog's core functionality has some awesome features that they've added - although I need to tweak some aspects.

I could just edit directly their Module code (Inside Index.php). Although this obviously would lead to update problems.

So what if I reference the Module from my Own Controller implementation of the Module, of the same name within my Vendor folder?

<?php
/**
 * Fetch the Third Parties' Original Implementation.
**/
require( "/app/code/[ThirdPartyVendor]/[SimpleBlog]/Controller/../Index.php" );

/**
 * My Vendor Namepace
**/
namespace MyVendor\SimpleBlogExtended\Controller\Post;

/**
 * My Class Implemention, Extending upon the original Third Party Class
**/
class Index extends \ThirdPartyVendor\SimpleBlog\Post
{
     //
     public function __construct()
     {
         //Extend the original functionality.
         parent::__construct();
     }

     //
     public function myNewFunctionality()
     {

     }
}
?>

But then this isn't clean, nor would this account for any other dependencies?

The other method I thought of - which is widely documented for extending the core, is di.xml Dictating the objectManager to take a perference of what to inject for a to-be-loaded class. Although this isn't a full module inheritance so to speak.

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema instance="...">
     <preference for="ThirdPartyVendor\SimpleBlog\Controller\Post.."
                 type="MyVendor\SimpleBlogExtended\Controller\Post.." />
</config>

Same methodology could be applied for routes.xml - taking precedence a request.

Apologies that this may seem very broad; but TLDR: Best Practice for extending a Module; not it's themes?

2 Answers 2

8
+50

And that's why they created plugins: http://devdocs.magento.com/guides/v2.1/extension-dev-guide/plugins.html

There are three types of plugins (before, around, after), which allow you to run your customizations relative to the function you want to extend.

You're right, using preferences may result in difficulties when upgrading, and should be used if plugins won't cut it.

There's also observers, but (opinion:) I think Magento will want to move away from them and double down on plugins.


Plugins also allow you to set a priority so you, or another vendor aren't stepping over each others toes:

The sortOrder property for plugins determine when their before, after, or around methods get called when several plugins are observing the same method.


Couple of things to be aware of when using plugins:

  • They only work on public functions

  • Using the around plugin can be dangerous because you can completely override the method you're trying to extend, and it can stop other plugins for running:

If the around method does not call the callable, it will prevent the execution of all the plugins next in the chain and the original method call.


If you're more familiar with the frontend, plugins are (also opinion:) kinda like the Mage/utils/wrapper Js module.

Checkout this answer as well: Magento 2 Plugin implementation for js frontend?

3
  • In that regards; a Plugin to intercept someone else's action? For E.g. saveBlogPost() - I could implement a Plugin that listens for this event, from a Third Party? aroundSaveBlogPost() for example?
    – MackieeE
    Nov 24, 2017 at 20:19
  • 1
    Exactly. Here's a good tutorial on how to do just that: coolryan.com/magento/2016/01/21/plugins-in-magento-2 Nov 24, 2017 at 20:49
  • IMHO Preferences and Plugins depending on the method/ additional functionality required will be the way to go.
    – NathanielR
    Nov 30, 2017 at 9:14
5

To extend any third-party Module's functionality you can use 2 ways as Override their class using preference or plugin.

But If you want to add your custom methods into their class you can choose preference.

Other than that you have to set dependencey as sequence in your custom module's etc/module.xml file

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="<Vendor_Modulename>" setup_version="1.0.0">
        <sequence>
            <module name="<ThirdPartyVendor_ThirdPartyModulename"/>         
        </sequence>
    </module>
</config>

If you directly change code of that third-party module or place any method into that third-party module's class that will be removed once new update will released.

So Only solution is either Override whole class and add your logic into that class or you can use around Plugin to extend logic of the method.

If you are looking to change into phtml file or xml file that you can do directly place that file into your module using same path.

Your Answer

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

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