12

In Magento 1, if you want to pass data from your Controller action to the "View" (i.e. a block in your layout, you can)

  1. Add a value/object to the global registry via Mage::register

  2. Directly fetch a block object and set data properties on the fetched block object after running loadLayout

  3. Call methods on block objects in phtml files, and have the block objects use the model/database layer to read data previously saved in the controller action

Using block object methods to read from the database still appears to work in Magento 2 -- which is appropriate for certain sorts of operations. However,

  1. There's no longer a global registry in Magento 2 (or is there?)

  2. The layout system now works by creating a page object via a factory, and you can't grab block references the same way you can in Magento 1

Is it possible in Magento 2 to pass data directly from a controller action down to a view? Or is this too direct a pattern for Magento's brave new Design Pattern™ world? If this is too direct a pattern, what should be doing if there's some calculated information we want to display in a template, but don't want to store that information into a stateful system (i.e. we don't want to save it to the database)

I can think of a few different way to hack this together myself -- but I'm interested in how Magento 2 wants you to do it.

Note: I realize it's possible to fetch a block instance in a controller action using something like this

$resultPage = $this->resultPageFactory->create();    
$block = $resultPage->getLayout()->getBlock('catalog.wysiwyg.js');        

var_dump(spl_object_hash($block));

The Magento 2 core code does this often. However -- the block object fetched in the controller object seems to be a different object than is available in a phtml template via either $this or $block (the former ($this) appears to be the object that actually renders the template, whereas the later ($block) appears to be an instance of the Magento Block type).

#File: path/to/template.phtml
var_dump(spl_object_hash($block));
var_dump(spl_object_hash($this));

I say "appears to be" because if I set data in the controller action method, it's not available in the phtml template -- and if I compare the spl_object_hash results above, I get three different hashes. However, I'm new enough to all this that the above might be some other error I've made -- so if you've been able to set data on blocks and fetch it in a template I'd love to hear about it!

2 Answers 2

17

Regarding #1, the registry does still exist, very similar to what you know from Magento 1. It's just moved. See: \Magento\Framework\Registry

Add it to your constructor via dependency injection, and then you can use your familiar $registry->register($key, $value) and $registry->registry($key) methods to store/access data.

I'd recommend poking around the \Magento\Framework namespace if you haven't already. A lot of what was accessible from Mage or App before is still there, just split out.

As far as best practices, I can't answer that, but I expect the answer would be to keep as much logic out of the controller as possible. Looking at the core is probably your best bet. For instance, see the customer address edit page: Basic controller; extensive block--including pulling the address ID and loading, if necessary. They handle that directly in the block; they don't do it in the controller and then pass it around.

3
  • 2
    The trick, of course, is knowing which parts for the core to look at, and which to ignore :) Thanks for the pointers, +1 for useful information! Sep 9, 2015 at 0:10
  • 1
    +1 for the last paragraph. If you need to share some calculated value, put the calculation behavior to separate object and call it from blocks that require that value. Registry is discouraged because it's global mutable state and you are never sure what you will get from there. Direct addressing of blocks from action is also discouraged because you are never sure if block is present on a page (layout can kill it)
    – Anton Kril
    Sep 9, 2015 at 8:53
  • @AntonKril how about page renderer helpers? CMS page helper, product view helper, are those meant to separate rendering from HTTP request? Sep 9, 2015 at 20:20
5

You should not passing Variables from Controller Action to View. Use block to for passing Variables to View (template engine).

5
  • Why? How could you pass get/post params from block to view? Isn't most logic pass them from controller to view?
    – LucScu
    Oct 17, 2016 at 8:43
  • Use Request Object in blocks. If you block get data from the controller through Registry, you cannot use it blocks with other controllers. It's called Temporal coupling and its bad practices
    – KAndy
    Oct 17, 2016 at 10:40
  • I use $block->assign() to pass request's params from controller to block. Is it also a bad practices?
    – LucScu
    Oct 17, 2016 at 16:49
  • Direct addressing of blocks from action is also discouraged because you are never sure if block is present on a page.
    – KAndy
    Oct 17, 2016 at 17:51
  • In my case i'm sure, because it is a custom scenario where controller, layout and block are only controlled by my code, so i think is logic pass request's params from controller to block. Thx for your replies!
    – LucScu
    Oct 18, 2016 at 6:53

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.