Categories


Archives


Recent Posts


Categories


Magento 2: $block and $this are NOT Interchangeable

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

In Magento 2, when you’re working in phtml template files, you’ll see two ways to make method calls to the block object, one using $this, another using $block

$this->someMethodCall();
$block->someMethodCall();

The $block variable is new in Magento 2. It contains a reference to an instance of a template’s block type. We say an instance because, unlike Magento 1, its not safe to assume you can set data on a block in one context (a controller action) and fetch it in another (a phtml template).

Why is there a $block variable? Because in Magento 2 $this refers to the template engine object. (a MagentoFrameworkViewTemplateEnginePhp object by default). Magento uses a bit of magic PHP in this class

#File: vendor/magento/framework/View/TemplateEngine/Php.php
public function __call($method, $args)
{
    return call_user_func_array([$this->_currentBlock, $method], $args);
}

public function __isset($name)
{
    return isset($this->_currentBlock->{$name});
}

public function __get($name)
{
    return $this->_currentBlock->{$name};
}

to ensure that calls to $this->someMethod() will be passed on to the current block object. i.e. if your old Magento 1 templates have code that looks like this

$this->someMethodHere();

and your block object has a someMethodHere method defined, Magento 2 will still call your block method.

However, this doesn’t make $this-> and $block-> interchangeable. First, the old Magento 1 helper method is no longer defined on a block object, its defined on the template engine object

#File: vendor/magento/framework/View/TemplateEngine/Php.php
public function helper($className)
{
    $helper = $this->_helperFactory->get($className);
    if (false === $helper instanceof MagentoFrameworkAppHelperAbstractHelper) {
        throw new LogicException($className . ' doesn't extends MagentoFrameworkAppHelperAbstractHelper');
    }

    return $helper;
}

i.e. – if you try to call

$block->helper(...);        

in Magento 2, you’ll get an error.

There’s another caveat for folks migrating Magento 1 code to Magento 2 – the following base abstract block methods no longer exist in Magento 2.

__
addCacheTag
addModelTags
addToChildGroup
addToParentGroup
countChildren
getAction
getAnonSuffix
getBlockAlias
getCacheLifetime
getCacheTags
getChild
getChildGroup
getHelper
getIsAnonymous
getItemsTags
getMessagesBlock
getSkinUrl
getSortedChildBlocks
getSortedChildren
getUrlBase64
getUrlEncoded
helper
htmlEscape
jsQuoteEscape
quoteEscape
setAnonSuffix
setBlockAlias
setFrameTags
setIsAnonymous
setMessagesBlock
setParentBlock
sortChildren
urlEscape

This means if any of your phtml templates from Magento 1 use one of these methods, you’ll need to find a replacement somewhere in Magento 2’s helper objects, or refactor them not to.

Copyright © Alan Storm 1975 – 2018 All Rights Reserved

Originally Posted: 2nd May 2016