How to override blocks in v2.1
Override block:
Create your own module under app/code
folder.
We can use preference
to override the class in Magento 2.
app/code/Vendor/Module/etc/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Theme\Block\Html\Topmenu" type="Vendor\Module\Block\Html\Topmenu" />
</config>
app/code/Vendor/Module/Block/Html/Topmenu.php
<?php
namespace Vendor\Module\Block\Html;
class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
protected function _addSubMenu($child, $childLevel, $childrenWrapClass, $limit)
{
}
}
Temporary solution:
Currently, seem that above steps cannot override the the block completely. We need to create new custom theme. And then, create the default.xml
file:
app/design/frontend/Vendor/Theme/Magento_Theme/layout/default.xml
<?xml version="1.0"?>
<page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<update handle="default_head_blocks"/>
<referenceBlock name="catalog.topnav" class="Vendor\Module\Block\Html\Topmenu" template="Magento_Theme::html/topmenu.phtml"/>
</page>
It's may be a Magento bug: Are we forced to rewrite a template in Magento2 when rewritting a block?
[EDIT]
1) We can set the template:
app/code/Vendor/Module/Block/Html/Topmenu.php
public function setTemplate($template)
{
return parent::setTemplate('Vendor_Module::custom-menu.phtml');
}
2) Set template via Xml:
For example:
app/code/Vendor/Module/view/frontend/layout/checkout_cart_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.cart">
<action method="setTemplate">
<argument name="template" xsi:type="string">Magento_Checkout::cart.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
Remember to create registration.php
and module.xml
.
We create the new module because we're overriding the class of Magento. When we want to override any class, we have to create new module.
The custom theme under app/design/frontend
contains:
--layout
--templates
--js
--html templates (Knockout templates)
--less, css
--etc...
Read more here and here.
Autoloading standard and naming convention:
For [Namespace]
and [Module]
, we should read more here:
http://www.php-fig.org/psr/psr-0/
http://www.php-fig.org/psr/psr-4/
http://alanstorm.com/magento_2_autoloader_and_class_generation
For override catalog product ListProduct block.
1) Create di.xml file in Folder Vendor/Module/etc
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Model\Product" type="Vendor\Module\Model\Rewrite\Catalog\Product" />
</config>
2) Create ListProduct.php Block file in Folder Vendor/Module/Block/Rewrite/Product
<?php
namespace Vendor\Module\Block\Rewrite\Product;
class ListProduct extends \Magento\Catalog\Block\Product\ListProduct
{
public function _getProductCollection()
{
// Do your code here
}
}
For override catalog product model.
1) Add preference in di.xml before
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Catalog\Model\Product" type="Vendor\Module\Model\Rewrite\Catalog\Product" />
</config>
2) Create Product.php Model file in Folder Vendor/Module/Model/Rewrite/Catalog
<?php
namespace Vendor\Module\Model\Rewrite\Catalog;
class Product extends \Magento\Catalog\Model\Product
{
public function isSalable()
{
// Do your code here
return parent::isSalable();
}
}
For Overriding Controller
1) Add preference in di.xml
2) Create View.php Controller file at Vendor/Module/Controller/Rewrite/Product
class View extends \Magento\Catalog\Controller\Product\View
{
public function execute()
{
// Do your stuff here
return parent::execute();
}
}
You can override other block,model and controllers using this same approach.