Magento 2: How to Get Object from Selected Product and Retrieve Attributes

magento2objectproductregistry

When a product gets clicked on -> the product details page opens and shows detailed information and images of the product. I want to display (programmatically) some custom product attributes(which I created via admin panel) on this page under the 'SKU#: sku123' section.

What I have done:

1.edit 'vendor/magento/module-catalog/view/frontend/layout/catalog_product_view.xml'

<block class="Magento\Catalog\Block\Product\View\Description" name="product.info.demo" template="product/view/warranty.phtml" after="product.info.price">   <arguments>
                        <argument name="at_call" xsi:type="string">getWarranty</argument>
                        <argument name="at_code" xsi:type="string">warranty</argument>
                        <argument name="css_class" xsi:type="string">warranty </argument>
                        <argument name="at_label" xsi:type="string">warranty </argument>
                        <argument name="add_attribute" xsi:type="string">itemprop="warranty "</argument>
                    </arguments>
            </block>

2.create warranty.phtml

<?php 
$_helper = $this->helper('Magento\Catalog\Helper\Output');
$_product = $block->getProduct(); // get current(selected) product object ?
$_code = $block->getAtCode();  
$_className = $block->getCssClass();
$_attributeLabel = $block->getAtLabel();
$_attributeType = $block->getAtType();
$_attributeAddAttribute = $block->getAddAttribute();

if ($_attributeLabel && $_attributeLabel == 'default') {
$_attributeLabel = $_product->getResource()->getAttribute($_code)-   >getFrontendLabel();
}
$_attributeValue =$_product->getResource()->getAttribute($_code)->getFrontend()->getValue($_product);
?>
<?php if ($_attributeValue): ?>
<div class="product attibute <?php echo $_className?>">
<?php if ($_attributeLabel != 'none'): ?><strong class="type"><?php echo     $_attributeLabel?>:</strong><?php endif; ?>
&ensp;<?php echo "test ". $_attributeValue; ?>
</div>
<?php endif; ?>

Code in Description.php:

    /**
 * @return Product
 */
public function getProduct()
{
    if (!$this->_product) {
        $this->_product = $this->_coreRegistry->registry('product');
    }
    return $this->_product;
}

This solves my problem, I can display my custom attribute 'warranty'.

What I understand: With registry-object we can set and get global variables. Here we get the global variable ('product'). And in phtml file we get the attribute value(from 'warranty') via this product-object.

What I dont understand: Who did set this global variable('product') ? How does _coreRegistry->registry('product'); magically give us the object of the currently (by the user) selected product ?

Also: Is there another way of getting the product-object (which corresponds to the currently selected product by the user) ?

I'm a little bit confused. Thanks in advance !

Best Answer

The registry value for 'product' is set when the Magento\Catalog\Controller\Product\View controller executes. More specifically, it occurs in Magento\Catalog\Helper\Product->initProduct. From what I can tell, the product Id and category Id are passed in as part of the actual product URL, which is rewritten to the product's url key. From the product view controller:

// Get initial data from request
        $categoryId = (int) $this->getRequest()->getParam('category', false);
        $productId = (int) $this->getRequest()->getParam('id');
        $specifyOptions = $this->getRequest()->getParam('options');