Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>It's a good question, but there isn't one clear answer. If you look at the Magento core itself, you'll see a variety of methods used. All that said, here's some general advice/context for the tradeoffs involved.</p> <p>Based on usage, Magento's controller action methods are <strong>not</strong> designed to interact with The View (or as it's known in Magento, The Layout). Instead, a controller action is meant as the main entry point for a specific URL, which should then interact with the request and do stuff with models. When that's done, the controller action then tells the layout to render with a calls to </p> <pre><code>$this-&gt;loadLayout(); $this-&gt;renderLayout(); </code></pre> <p>As designed (and this is just an opinion) The Layout is completely decoupled from the rest of the system. CodeIgniter/Kohana style systems feature "dumb views", which take variables from the controller action and do a simple template replacement on them. The Magento Layout, on the other hand, is a collection of nested block objects, and block object methods are meant to <strong>query the models directly</strong> when they need information. </p> <p>For example — take a look at the <code>Mage_Adminhtml_Block_Catalog_Product_Attribute_Set_Main_Formset</code> block</p> <pre><code>#File: app/code/core/Mage/Adminhtml/Block/Catalog/Product/Attribute/Set/Main/Formset.php protected function _prepareForm() { $data = Mage::getModel('eav/entity_attribute_set') -&gt;load($this-&gt;getRequest()-&gt;getParam('id')); //... } </code></pre> <p>The idea here is, irrespective of what happens in the controller action, the <code>Mage_Adminhtml_Block_Catalog_Product_Attribute_Set_Main_Formset</code> block will always grab the latest <code>eav/entity_attribute_set</code> model information when it renders (accessing the request object to get the request/post data, as you mentioned above). The controller action and the view are decoupled from one another.</p> <p>As designed, the is The Right way to use the system. Unfortunately, it's also ineffective from a performance standpoint. For developers coming form other systems, the idea that view rendering kicks off another round of SQL queries seems crazy. Magento's famous "start shooting and let the caching layer" sort it out approach met with mixed results. </p> <p>One remedy for this potential performance problems is where stashing already instantiated models in the registry comes into play. You can see an example of this in the admin console's product editing controller</p> <pre><code>#File: app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php protected function _initProduct() { //... Mage::register('current_product', $product); //... } </code></pre> <p>and then its use in many of the resulting blocks which render the editing form for products</p> <pre><code>app/code/core/Mage/Adminhtml/Block/Catalog/Product/Edit/Js.php public function getProduct() { return Mage::registry('current_product'); } </code></pre> <p>The trade-off here is better SQL performance (no extra queries for the blocks), but you've essentially tied these blocks to a controller action which defines a <code>current_product</code> registry entry. The Magento registry is (in essence) a fancy way of doing global variables, so you have most of the problems inherent with globals. As you noted, you can achieve similar results with the <code>getSingleton</code> method — but that may not be appropriate depending on the task you're trying to accomplish. </p> <p>For what it's worth, the registry/singleton method appears to be favored by the core developers for both the admin console application (the <code>Mage_Adminhtml</code> module) and the Magento Mobile controllers (the <code>Mage_XmlConnect</code> module), while the more paranoid "load the model explicitly" pattern is used more in the front-end cart application. Whether this is a coincidence, a conscious choice, or just the core team itself learning as it went along is probably one of those unanswerable questions. </p> <p>Finally, one technique that's not used much by the core code, but that I sort of like when I'm looking for more of a "dumb view" behavior, is this. After you load the layout, but before you render it, you're able to access specific blocks by name. This, combined with the power of magic getters and setters, lets you do something like this</p> <pre><code>$this-&gt;loadLayout(); $content = $this-&gt;getLayout()-&gt;getBlock('content'); if($content) { $content-&gt;setSomeValue('Hello World'); } $this-&gt;renderLayout(); </code></pre> <p>and then from your block's template, you can grab the variable with</p> <pre><code>echo $this-&gt;getSomeValue(); </code></pre> <p>You're still tying your block's implementation to your controller action but doing so in a less global-ish way. Also, the decoupled layout may not contain the block you're looking for, so you'll want to be careful with this. </p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload