8

During module development I've been writing a plugin which modifies the product options collection before it was loaded (adds a description field). Here is it:

etc/di.xml

<type name="Magento\Catalog\Model\ResourceModel\Product\Option\Collection">
    <plugin name="addOptionDescription" type="Vendor\Module\Plugin\Product\Option\Collection" sortOrder="10" disabled="false"/>
</type>

Code:

<?php
namespace Vendor\Module\Plugin\Product\Option;

use Vendor\Module\Model\OptionDescription;
use Magento\Catalog\Model\ResourceModel\Product\Option\Collection as OptionCollection;

class Collection
{
    /**
     * @var \Vendor\Module\Helper\Data
     */
    protected $helper;

    public function __construct(
        \Vendor\Module\Helper\Data $helper
    ) {
        $this->helper = $helper;
    }

    /**
     * @param OptionCollection $subject
     * @param bool $printQuery
     * @param bool $logQuery
     * @return array
     */
    public function beforeLoad($subject, $printQuery = false, $logQuery = false)
    {
        if (!$subject->isLoaded()) {
            $this->addDescriptionToResult($subject);
        }

        return [$printQuery, $logQuery];
    }

    /**
     * Add description to result
     *
     * If yo get error message "Warning: Illegal string offset 'is_in_stock' ... "
     * @see http://devdocs.magento.com/guides/v2.0/install-gde/trouble/php/tshoot_opcache.html
     *
     * @param OptionCollection $collection
     * @return OptionCollection $collection
     */
    private function addDescriptionToResult($collection)
    {
        $tableName = OptionDescription::TABLE_NAME;
        $joinDescriptionExpr = 'main_table.unique_option_id = option_description.unique_option_id AND option_description.store_id = 0';

        $collection->getSelect()->joinLeft(
            ['option_description' => $tableName],
            $joinDescriptionExpr,
            ['description' => 'description']
        );

        return $collection;
    }

    /**
     * Resolve current store id
     *
     * @return int
     */
    protected function getStoreId()
    {
        return $this->helper->resolveCurrentStoreId();
    }
}

Everything seems to be ok, but... When I try to load the existing product edit page (on backend) I see the following error:

Warning: Illegal string offset 'is_in_stock' in [...]/vendor/ magento/module-catalog-inventory/Ui/DataProvider/Product/Form/ Modifier/AdvancedInventory.php on line 87

In case I make changes as it is indicated in docs (set opcache.save_comments = 1 inside mine php-fpm config) everything works fine. But I can't understand, which code causes the error above and how can I prevent it without config modifications ?

2

The ExtensionAttributesFactory (and not only) uses the dockblocks to determine "stuff". (not sure yet what exactly).
If you use OP cache, this means your php files will be cached, minified and will probably suffer other modifications.
By default the opcache does not save the comments in the minified version so $methodDocBlock = $methodReflection->getDocComment(); will return null and there is no way to find out meta data about the methods in a certain interface.

I know it's not a full answer, but the idea is in here. Magento uses the dockblocks to find out meta data about methods so you need to keep them.

  • Thank you for your answer. I think this means that I can not prevent this error without configuration modifications. – Siarhey Uchukhlebau Jul 5 '17 at 7:07

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.