0

After a long suffering, I found that I've to use DI instead of object manager. However I'm trying to create block in custom module and call the method in success.phtml. But I got the following error : An error has happened during application run. See exception log for details.

My block file :

<?php
namespace Nectar\Google\Block;

private $_objectManager;

 public function __construct(\Magento\Framework\ObjectManagerInterface $objectmanager)
   {
           $this->_objectManager = $objectmanager;
   }
   public function GrandTotal()
   {               
       $oid = $this->_objectManager->create('Magento\Sales\Model\Order')->loadByIncrementId($block->getOrderId());
       return $order->getGrandTotal($oid);
   }

In success.phtml :

$block = $this->block(Nectar\Google\Block\order);
$total = $block->GrandTotal();

I feel that I mad a mistake but I don't know where.. could you please help me.

2
  • Is this a whole code or a snippet - because class wrapper is missing Commented Aug 9, 2022 at 21:18
  • I'm putting together a reasonably detailed answer for how to do this, in the mean-time... what is the error in the exception log?
    – Craig
    Commented Aug 10, 2022 at 19:17

1 Answer 1

0

First off I would start by checking the contents of the exception log as stated in the error that Magento has provided as that will help you track down issues much easier.

In this answer I'm going to break-down the thought process I used to get to this answer and at the end I'll paste the full code.

It looks like you kinda understand the concept of DI but are not quite there.

Let's take it back a couple of steps and solve the problem from the start.

We want to add the Grand Total into the success page. In an ideal world we want to be able to inject content into the page without overriding it. Looking at Magento_Checkout::success.phtml (Note: depending on the version of Magento you are using the code and line numbers may be slightly different) we can see <?= $block->getAdditionalInfoHtml() ?> suggesting there is a way to inject other content in. Looking at the method it calls $this->_layout->renderElement('order.success.additional.info') which is great, as that means we can add a block to the element being rendered.

Doing a search for order.success.additional.info inside vendor/magento we can see there is a container defined as <container name="order.success.additional.info" label="Order Success Additional Info"/> within vendor/magento/module-checkout/view/frontend/layout/checkout_onepage_success.xml, so we can define our own block using a custom template without messing with the core one. (Before anyone says, yes, I am well aware that adding cacheable="false" to the layout will disable FPC but the success page should never be cached)

Now we have a block we can work on the block class to provide methods to our template. We will need to get the data for the order that was just placed, which is available using the checkout session, so we should inject the CheckoutSession as a dependancy. (Note: Session objects should be injected into our block using a Proxy but I'm going to skip over this for the sake of simplicity.) We can grab the order data from the checkoutSession using getLastRealOrder().

Now let's pull it all together in our block class. We'll create a getGrandTotal() methods to get the total from the session, which we can do using getGrandTotal(), BUT it would probably look better formatted with the currency symbol and the correct number of decimal points. getGrandTotal() will return a string value such as 38.0000. Luckily the Order object from the session provides a formatPrice() method. Because our Block class needs to extend \Magento\Framework\View\Element\Template we need to provide it's parent class its dependancies via the constructor which is why we also need to pass in Template\Context as well as the $data array.

First our layout file where we define our block app/code/Nectar/Google/view/frontend/layout/checkout_onepage_success.xml:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="order.success.additional.info">
            <block class="Nectar\Google\Block\MyBlock" name="your.block.name" template="Nectar_Google::success.phtml" cacheable="false"/>
        </referenceContainer>
    </body>
</page>

Next is our template app/code/Nectar/Google/view/frontend/templates/success.phtml:

<?php
/** @var \Nectar\Google\Block\MyBlock $block */
?>
<h1><?= $block->getGrandTotal() ?></h1>

Finally our block class app/code/Nectar/Google/Block/MyBlock.php:

<?php declare(strict_types=1);

namespace Nectar\Google\Block;

use Magento\Checkout\Model\Session;
use Magento\Framework\View\Element\Template;

class MyBlock extends Template
{
    /** @var Session */
    private $checkoutSession;

    /**
     * @param Template\Context $context
     * @param Session $checkoutSession
     * @param array $data
     */
    public function __construct(
        Template\Context $context,
        Session $checkoutSession,
        array $data = []
    ) {
        $this->checkoutSession = $checkoutSession;
        parent::__construct($context, $data);
    }

    public function getGrandTotal()
    {
        $order = $this->checkoutSession->getLastRealOrder();
        return $order->formatPrice($order->getGrandTotal());
    }
}

The final result is this: Final Result

Hopefully this explains the bits you were missing out on.

3
  • It's didn't work, because my main success.phtml is in module-inventory-in-store-pickup-frontend
    – Dun7ill
    Commented Aug 11, 2022 at 8:56
  • Hi @Craig.. Thank a lot :) It's solved now by calling the block by $totall = $this->getLayout()->createBlock('\Nectar\Google\Block\Success')->getGrandTotal(); But how I can get the other order data like email, telepohne & addrees ?
    – Dun7ill
    Commented Aug 11, 2022 at 9:25
  • I got it by using getCustomerData.. Thank you very much :).
    – Dun7ill
    Commented Aug 11, 2022 at 9:56

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.