Zend certified PHP/Magento developer

Need a block to cache its result regardless if it called from the controller or the template

I have a block with a function getParts() which is called from a template. This function does a bunch of queries and returns an array of data. I need to make it so if it does not return any data, a 404 is generated.

I was able to successfully do this by injecting the block into the controller’s __construct and then have code in the controller like:

public function execute()
{
    $resultPage = $this->resultPageFactory->create();

    // If there were no parts returned by the parts block then redirect to a 404
    if (count($this->myBlock->getParts()) === 0) {
        $resultForward = $this->resultForwardFactory->create();
        $resultForward->forward('noroute');
        return $resultForward;
    }

    return $resultPage;
}

All this works correctly, however, that getParts() function takes a while to run so I modified the block’s getParts() to be something like:

    if (is_array($this->partsData)) {
        return $this->partsData;
    }
    else {
        // My time intensive code here
    }

So in theory this should cache the data so getParts() should only do all its lookups once, then on the second call to getParts() it will just return what it previously retrieved and stored in $this->partsData.

This caching isn’t working, however. It looks like the controller is calling the block’s function first, then the template is calling it later, but I think the block is really being created twice, once by the controller and once by the template, so when $this->partsData is checked it is empty both times.

How can I make it so the controller is sharing the same block object, so when getParts() is called the second time it doesn’t have to do this lookup? Or, if there is some other way to generate a 404 from the block that could also work.