16

I get this error on some products that have related products:

Warning: Invalid argument supplied for foreach() in vendor/magento/module-catalog/Block/Product/ProductList/Related.php on line 129

This issue only happens when full page cache is on. Unfortunately disabling it is not an option as the speed difference is huge (more than 2 seconds faster with page cache).

I tried everything that I know: removing our theme, custom modules etc.

Environment: production, 2.1.0, varnish.

This is the full stack trace:

a:4:{i:0;s:190:"Warning: Invalid argument supplied for foreach() in vendor/magento/module-catalog/Block/Product/ProductList/Related.php on line 129";i:1;s:5441:"#0 vendor/magento/module-catalog/Block/Product/ProductList/Related.php(129): Magento\Framework\App\ErrorHandler->handler(2, 'Invalid argumen...', '/home/11396-492...', 129, Array)
#1 var/generation/Magento/Catalog/Block/Product/ProductList/Related/Interceptor.php(37): Magento\Catalog\Block\Product\ProductList\Related->getIdentities()
#2 vendor/magento/module-page-cache/Model/Layout/LayoutPlugin.php(71): Magento\Catalog\Block\Product\ProductList\Related\Interceptor->getIdentities()
#3 vendor/magento/framework/Interception/Interceptor.php(152): Magento\PageCache\Model\Layout\LayoutPlugin->afterGetOutput(Object(Magento\Framework\View\Layout\Interceptor), '    <script>\n  ...')
#4 var/generation/Magento/Framework/View/Layout/Interceptor.php(494): Magento\Framework\View\Layout\Interceptor->___callPlugins('getOutput', Array, Array)
#5 vendor/magento/framework/View/Result/Page.php(243): Magento\Framework\View\Layout\Interceptor->getOutput()
#6 vendor/magento/framework/View/Result/Layout.php(164): Magento\Framework\View\Result\Page->render(Object(Magento\Framework\App\Response\Http\Interceptor))
#7 vendor/magento/framework/Interception/Interceptor.php(74): Magento\Framework\View\Result\Layout->renderResult(Object(Magento\Framework\App\Response\Http\Interceptor))
#8 vendor/magento/framework/Interception/Chain/Chain.php(70): Magento\Framework\View\Result\Page\Interceptor->___callParent('renderResult', Array)
#9 vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'renderResult', Object(Magento\Framework\View\Result\Page\Interceptor), Array, 'result-varnish-...')
#10 vendor/magento/module-page-cache/Model/Controller/Result/VarnishPlugin.php(74): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Framework\App\Response\Http\Interceptor))
#11 vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\PageCache\Model\Controller\Result\VarnishPlugin->aroundRenderResult(Object(Magento\Framework\View\Result\Page\Interceptor), Object(Closure), Object(Magento\Framework\App\Response\Http\Interceptor))
#12 vendor/magento/framework/Interception/Chain/Chain.php(63): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'renderResult', Object(Magento\Framework\View\Result\Page\Interceptor), Array, 'result-builtin-...')
#13 vendor/magento/module-page-cache/Model/Controller/Result/BuiltinPlugin.php(67): Magento\Framework\Interception\Chain\Chain->Magento\Framework\Interception\Chain\{closure}(Object(Magento\Framework\App\Response\Http\Interceptor))
#14 vendor/magento/framework/Interception/Chain/Chain.php(67): Magento\PageCache\Model\Controller\Result\BuiltinPlugin->aroundRenderResult(Object(Magento\Framework\View\Result\Page\Interceptor), Object(Closure), Object(Magento\Framework\App\Response\Http\Interceptor))
#15 vendor/magento/framework/Interception/Interceptor.php(138): Magento\Framework\Interception\Chain\Chain->invokeNext('Magento\\Framewo...', 'renderResult', Object(Magento\Framework\View\Result\Page\Interceptor), Array, 'aw_layerednav_r...')
#16 app/code/Aheadworks/Layerednav/Model/Plugin/Result.php(75): Magento\Framework\View\Result\Page\Interceptor->Magento\Framework\Interception\{closure}(Object(Magento\Framework\App\Response\Http\Interceptor))
#17 vendor/magento/framework/Interception/Interceptor.php(142): Aheadworks\Layerednav\Model\Plugin\Result->aroundRenderResult(Object(Magento\Framework\View\Result\Page\Interceptor), Object(Closure), Object(Magento\Framework\App\Response\Http\Interceptor))
#18 var/generation/Magento/Framework/View/Result/Page/Interceptor.php(130): Magento\Framework\View\Result\Page\Interceptor->___callPlugins('renderResult', Array, Array)
#19 vendor/magento/framework/App/Http.php(139): Magento\Framework\View\Result\Page\Interceptor->renderResult(Object(Magento\Framework\App\Response\Http\Interceptor))
#20 vendor/magento/framework/App/Bootstrap.php(258): Magento\Framework\App\Http->launch()
#21 index.php(39): Magento\Framework\App\Bootstrap->run(Object(Magento\Framework\App\Http))
#22 {main}";s:3:"url";s:15:"/pecan-pie.html";s:11:"script_name";s:10:"/index.php";}

Any ideas where to look?

At line 129 in vendor/magento/module-catalog/Block/Product/ProductList/Related.php $this->getItems() is null:

  /**
     * Return identifiers for produced content
     *
     * @return array
     */
    public function getIdentities()
    {
        $identities = [];
        var_dump($this->getItems());
        foreach ($this->getItems() as $item) {
            $identities = array_merge($identities, $item->getIdentities());
        }
        return $identities;
    } 

Thanks!

  • Have you rewrite Related.php in your module? – Rakesh Jesadiya Nov 2 '16 at 10:28
  • @Rakesh no. just greped everything. No related class except the magento one and tests. – Claudiu Creanga Nov 2 '16 at 10:35
  • 1
    Seems like this error only occurs when cache is on – Stevie G Nov 18 '16 at 5:58
  • 1
    So when you chance the product view from a 2 column layout to a single column layout it causes this error – Stevie G Nov 18 '16 at 6:10
  • Please answer your question if you have an answer – Stevie G Nov 18 '16 at 6:12
2

In the same Class (vendor/magento/module-catalog/Block/Product/ProductList/Related.php) there is a method as shown below. This is where the item collection is set and then used in the getItems() method you are calling. Debug here and confirm the item collection is getting some results. As you can see some filters are being applied in this code, so there is a chance that products are not passing through those filters.

/**
     * @return $this
     */
    protected function _prepareData()
    {
        $product = $this->_coreRegistry->registry('product');
        /* @var $product \Magento\Catalog\Model\Product */

        $this->_itemCollection = $product->getRelatedProductCollection()->addAttributeToSelect(
            'required_options'
        )->setPositionOrder()->addStoreFilter();

        if ($this->moduleManager->isEnabled('Magento_Checkout')) {
            $this->_addProductAttributesAndPrices($this->_itemCollection);
        }
        $this->_itemCollection->setVisibility($this->_catalogProductVisibility->getVisibleInCatalogIds());

        $this->_itemCollection->load();

        foreach ($this->_itemCollection as $product) {
            $product->setDoNotUseCategoryId(true);
        }

        return $this;
    }
1

Just hit this bug in 2.1.7 CE.

I'm 90% sure this is because getIdentities() is "often" called before _beforeToHtml(). This means _prepareData() is never called so _itemCollection is empty. This makes a bit of sense because the cache wants to know whats what before it generates the html (and as noted getIdentites() is cache related).

So getIdentities needs to call _prepareData()

public function getIdentities()
{
    $this->_prepareData();

and _prepareData() needs to defend itself from running twice.

protected function _prepareData()
{
    if($this->_itemCollection)
        return $this;

Then everything is fine.

Edit: Just found this closed bug report https://github.com/magento/magento2/issues/5897 Should be fixed in future release.

0

What you could try is add the following to your template layout file where this layout block is defined:

<action method="unsetData"><key>cache_lifetime</key></action>
<action method="unsetData"><key>cache_tags</key></action>

Add it to the top of the block like so:

<module_index_index>
     <action method="unsetData"><key>cache_lifetime</key></action>
     <action method="unsetData"><key>cache_tags</key></action>
     // the actions that are defined
</module_index_index>

The code above means you are not caching this layout block.

If this works it means that the caching wont allow you to keep the data or it is overwritten by something else making it empty? (guessing here)

-4

try this code:

$model = Mage::getModel('catalog/product');
$product = $model->load($product_id);

// Get all related product ids of $product.
$allRelatedProductIds = $product->getRelatedProductIds();

foreach ($allRelatedProductIds as $id) {
            $relatedProduct = $model->load($id);

            // get Product's name
            echo $relatedProduct->getName();

            // get product's short description
            echo $relatedProduct->getShortDescription();

            // get Product's Long Description
            echo $relatedProduct->getDescription();

            // get Product's Regular Price
            echo $relatedProduct->getPrice();

            // get Product's Special price
            echo $relatedProduct->getSpecialPrice();

            // get Product's Url
            echo $relatedProduct->getProductUrl();

            // get Product's image Url
            echo $relatedProduct->getImageUrl();

        }
-6

We ran into this problem. Check if the product (not the related products) is out of stock. Putting the product in stock solved the issue for us.

  • This does not solve the problem though, it avoids the problem – Stevie G Nov 24 '16 at 15:03
  • This is not a solution – harri Jun 11 '17 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.