2

I want to omit all object manger-like methods.

Is there any smart way to add customer session object (for example check logged/non-logged user to display different content) into template? Of course it can be done via DI in each block we need but it needs a lot of overriding which is not a good solution.

Maybe it can be done by injecting it in di.xml as argument to desired blocks?

Or just adding it to context block somehow?

5

3 Answers 3

1

Maybe it can be done by injecting it in di.xml as argument to desired blocks?

Not in di.xml, because this is all about the constructor parameters and since you don't want to create new block classes, this option is dropped.

But you can add arguments via layout XML, like this:

<referenceBlock name="the-block-name">
  <arguments>
    <argument name="customer_session" xsi:type="object">Magento\Customer\Model\Session</argument>
  </arguments>
</referenceBlock>

Now you can reference the session in your template with

$block->getCustomerSession()

Documentation: http://devdocs.magento.com/guides/v2.1/frontend-dev-guide/layouts/xml-instructions.html


However, just because this is possible, it does not mean that it is the best solution. In my opinion, this is the same kind of dependency than using the object manager in the template, it's just hidden well, which makes it even worse.

From the code there is no evidence of the dependency anymore, and the template only works if this argument is passed via layout XML.

A new block class is the better option. But you should not override the original block via DI preferences, but rather change the block type together with the template via layout XML. Now the new template is coupled with the new block type and its dependency to the session is explicit in code.

2
  • thank you for great answer! I see the point and agree if it just like using Object Manager it is not good solution. What do you exactly mean by ` change the block type together with the template via layout XML.` Can you develop your answer? Should I just remove core block in xml and in that place add some custom block extending from core one with additional dependency? Commented Dec 22, 2016 at 12:49
  • 1
    @lord_of_strings yes, that's the idea. I think overriding the class via XML is still not possible in Magento 2, so you have to replace the block Commented Dec 22, 2016 at 18:29
2

In Magento 1, you had the option to handle things with the customer_logged_in or customer_logged_out handle. Those handles are not available anymore in Magento 2. Instead of using a Session in you templates, you could add the missing handles by an Observer and add your changes via layout.xml.

Check out here: MAGENTO 2 : GET CUSTOMER_LOGGED_IN AND CUSTOMER_LOGGED_OUT LAYOUT HANDLES

In case the first way doesn't solve your problem, you could inject your session into the object you need by constructer injection. Navigate to you block, and add the session object to your constructer:

/**
 * YOURBLOCK constructor.
 *
 * @param Template\Context                    $context
 * @param \Magento\Backend\Model\Auth\Session $authSession
 * @param array                               $data
 */
public function __construct(
    Template\Context $context, 
    \Magento\Backend\Model\Auth\Session $authSession, 
    array $data = []
) {
    parent::__construct($context, $data);
    $this->authSession = $authSession;
}
2
  • +1 for adding handle, but adding argument like this to construct is not a solution in case of core blocks if we don't want to override it. Commented Dec 22, 2016 at 9:15
  • You don't have to overwrite it as the way you would in Magento 1. You have a couple of possibilities. You could add your own block, which extends the Core one and add your session to the construct. You also could try to manage the dependency by your di. I would prefer to add an own block Commented Dec 23, 2016 at 20:19
2

You can create a helper for that and using it on your codes.

<?php $helper = $this->helper('Vendor\Checklog\Helper\Data'); ?>

call helper like this.

Helper codes to check logged in -

<?php
namespace Vendor\Checklog\Helper;

use Magento\Customer\Model\Context;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * @var \Magento\Framework\App\Http\Context
     */
    protected $_httpContext;

    /**
     * @param \Magento\Framework\App\Http\Context $httpContext
     * 
     */
    public function __construct(
        \Magento\Framework\App\Http\Context $httpContext
    ) {
        $this->_httpContext = $httpContext;
    }

    public function isLoggedIn()
    {
        if($this->_httpContext->getValue(Context::CONTEXT_AUTH)) {
            return true;
        }
        return false;
    }
}
4
  • Helper approach is portable so it can be really useful, but I think it is more correct to obtain info from customer session object Commented Dec 22, 2016 at 9:22
  • 1
    If you get info from customer session object that will not work in all pages with Full page cache enabled. With full page cache enabled it will work with only with the templates which block scope is defined as private, such as customer account pages, cart, contact etc. In that case you need to define separate block/phtml for each time you use it. To find the whether logged in or not, it is the most portable way. But I personally prefer the di injection methods using on my block. There should be no shortcut when you want to write good codes.
    – Sandipan S
    Commented Dec 22, 2016 at 9:48
  • But injecting it __construct() can be done via di.xml and node argument right? I don't have to add preference on every block I want to modify and override its contructor? Commented Dec 22, 2016 at 9:51
  • yes, exactly. same as the constructor above. vote me up if it helps you.
    – Sandipan S
    Commented Dec 22, 2016 at 10:09

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.