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?
Best Answer
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:
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 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?