0

I am trying to add a new function into the Magento\Catalog\Block\Product\View by extending the class. I tried to use that function in the template which is getHelloWorld() but I can't seem to get the function to work

etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Catalog\Block\Product\View" type="My\Module\Block\Catalog\Product\View" />
</config>

My/Module/Block/Catalog/Product/View.php

<?php

namespace My\Module\Block\Catalog\Product;

class View extends \Magento\Catalog\Block\Product\View
{
     public function getHelloWorld()
     {
         return 'Hello World';
     }
}

design/frontend/theme/folder/Magento_Catalog/templates/product/view/type/default.phtml

<?php $_product = $block->getProduct() ?>

//-----added it here this
<?php echo $block->getHelloWorld() ?>


<?php if ($block->displayProductStockStatus()): ?>
    <strong>Availability</strong>: 
    <?php if ($_product->isAvailable()): ?>
        <span class="stock available" title="<?= /* @escapeNotVerified */ __('Availability') ?>">
            <span><?= /* @escapeNotVerified */ __('In stock') ?></span>
        </span>
    <?php else: ?>
        <span class="stock unavailable" title="<?= /* @escapeNotVerified */ __('Availability') ?>">
            <span><?= /* @escapeNotVerified */ __('Out of stock') ?></span>
        </span>
    <?php endif; ?>
<?php endif; ?>

1 Answers1

2

You really don't need to overwrite the class just to add some data. You would only want to overwrite that class for major changes. Otherwise, observers and plugins are available to you.

To modify block or model data or behavior, here is my order of preference, from least intrusive to "OMG you better have a good reason for doing this".

  1. Plugin: before, around, or after. Alan Storm does an excellent plugin tutorial here.
  2. Observer: There are several observers available which will allow you to change the data or behavior of the block in question.
  3. Argument Replacement: More Magento awesomeness where you can replace a single instance of the class instead of EVERY usage of the class which is what happens when you use 'preference'.
  4. Preference: This is a class rewrite. Unless you have major changes, you should really ask yourself "what's so special about my changes that I need to take full ownership of this class when the Magento core team lovingly created all of these other fantastic and more efficient ways to achieve my goal?".

The block you mentioned uses magic methods. If you create a plugin or observer and do $block->setHelloWorld('some text here'), and then in the actual template do echo $block->getHelloWorld(), 'some text here' will be printed out in the template even though the 'getHelloWord' method doesn't actually exist.


A little more explanation.

Any class that inherits from \Magento\Framework\DataObject has access to the magic methods. In that class, the __call method checks to see if the function being called begins with get, set, uns, or has. If it does and there is a concrete method that matches, that method will be called. Otherwise, depending on what three letters the function begins with, it will convert your function name as per the example below:

getHelloWorld will become $this->getData('hello_world')
setHelloWorld('some value') will become $this->setData('hello_world', 'some value')
unsHelloWorld will become $this->unsetData('hello_world')
hasHelloWorld will do a check to see if any element with the key hello_world exists in the class's $this->_data array.

I hope this helps you out!

Shawn Abramson
  • 3,555
  • 1
  • 17
  • 22
  • I only plan to add a new function into \Magento\Catalog\Block\Product\View, I will be changing the 'some value' to will auto generated text. I tried doing this with a plugin public function afterGetProduct(\Magento\Catalog\Block\Product\View $subject, $result) { $this->setData('hello world', 'some value'); return $result; } and with the phtml $block->getHelloWorld() does not work – JustBigBoy12345 May 04 '18 at 00:01
  • I seen this on https://magento.stackexchange.com/a/160900/67225 but their solution is almost the same as what I want to do, but it doesn't work – JustBigBoy12345 May 04 '18 at 00:03
  • @JustBigBoy12345 can you clarify a little more about how the function should work? I mean I can show you how to easily override and extend the class but it goes against Magento's best practices so I am trying to make the effort to push you in the right direction. – Shawn Abramson May 04 '18 at 00:10
  • Also, when overriding a class to add one function only, that's usually an indicator that you're thinking about it in the wrong way. Explain a little bit and I'll do my best to get you going. – Shawn Abramson May 04 '18 at 00:12
  • I am trying to display the last quantity of the product bought by the logged in customer and have a button as a shortcut to add the same amount into the cart. – JustBigBoy12345 May 04 '18 at 02:30
  • Thanks for the clarification. You definitely don't need to override the class to do this, now that I know what you want to accomplish. Where are you thinking of displaying the button? Either tell me the specific template you wanted it to live in or just general area of the page. And is this only for product pages? – Shawn Abramson May 04 '18 at 02:32
  • I saw how the default.phtml has the $_product->isAvailable() and I was thinking of putting it in the default.phtml where it checks if the product is available or not. – JustBigBoy12345 May 04 '18 at 02:39
  • @JustBigBoy12345 one more question. Are you doing this inside of a theme or you have an extension that you built? – Shawn Abramson May 04 '18 at 02:49
  • @JustBigBoy12345 I whipped up an extension for you that does exactly this. It's almost finished. Could you post a new question explaining the exact requirement and I will post it there? Also, I wouldn't be offended if you accepted and upvoted my answer on this question as the answer is valid :-) – Shawn Abramson May 04 '18 at 03:15
  • I was going to build a new extension for it. Ok sure, and thank you – JustBigBoy12345 May 04 '18 at 03:18
  • Ok I tried to explain what i needed on this page https://magento.stackexchange.com/questions/224678/displaying-last-bought-quantity-by-current-customer-in-product-view-page – JustBigBoy12345 May 04 '18 at 03:34
  • Ok, im just trying to wrap it up. Will be there soon. – Shawn Abramson May 04 '18 at 03:34
  • @JustBigBoy12345 I am about to start posting the files in the new question. Would greatly appreciate if you could hook me up with an accept and upvote on this current question. Thanks – Shawn Abramson May 04 '18 at 04:01