phpmagentomagento2

Magento2: Argument 1 [...] must be an instance of Magento\Framework\App\Helper\Context


First of all, I'm quite new to Magento 2, but I've used Magento 1.x for some time.

I've read a lot about how to solve DI-related problems, but I'm stuck on this one:

Exception #0 (Exception): Recoverable Error: Argument 1 passed to Cefar\AO\Helper\Ao::__construct() must be an instance of Magento\Framework\App\Helper\Context, instance of Magento\Framework\ObjectManager\ObjectManager given, called in .../vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 93 and defined in .../Cefar/AO/Helper/Ao.php on line 11

Many other answers have suggested deleting the var/di and var/generation folders, sometimes var/cache also. While this solves the problem, it occurs again once bin/magento setup:di:compile is run, which means the code cannot be used in a production environment.

I've checked that the Ao class does not instantiate any objects. It also doesn't try to re-make any objects that could be provided by the context given. Here's the code:

namespace Cefar\AO\Helper;

class Ao extends \Magento\Framework\App\Helper\AbstractHelper
{
    const DEFAULT_GRID_COLS = 4;

    protected $_session;

    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Customer\Model\Session $session
    )
    {
        parent::__construct($context);
        $this->_session = $session;
    }

    public function getConfig($path)
    {
        return $this->scopeConfig->getValue($path);
    }

    public function isActive($url = null, $print = true) {
        $active = ($url && strstr($_SERVER['REQUEST_URI'], $url) !== false);

        if ($active && $print) {
            echo "active";
        } else {
            return $active;
        }
    }

    public function isLoggedIn()
    {
        return $this->_session->isLoggedIn();
    }

    public function limitWords($text = '', $limit = 10, $showDots = true)
    {
        $words = explode(' ', $text);
        $limited = array_slice($words, 0, $limit);
        $newText = implode(' ', $limited);

        if (count($words) > $limit && $showDots) {
            $newText .= '...';
        }

        return $newText;
    }

    public function getCurrentGrid()
    {
        return ($this->_getRequest()->getParam('grid'))
            ? $this->_getRequest()->getParam('grid')
            : self::DEFAULT_GRID_COLS;
    }
}

There's nothing particularly special here. I'm confused as to how this is even happening; every other defined class in the extension is getting its DI parameters correctly. Why is the ObjectManager apparatus providing an unwanted argument? The relevant call is given in the error report as:

.../vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php(93): Cefar\AO\Helper\Ao->__construct(Object(Magento\Framework\ObjectManager\ObjectManager))

So it isn't even providing two arguments!

I've also read about providing type hints in a di.xml, but it doesn't seem to be relevant here as both types are part of the Magento libraries? I note that there is an entry for Magento\Framework\App\Helper\Context but not one for Magento\Customer\Model\Session... but that there are framework classes that use ID to import Magento\Customer\Model\Session already which work.


Solution

  • Long story short, this was because of a typo.

    Sometimes when the helper was being included, it was being referred to as Cefar\AO\Helper\Ao, and other times, Cefar\AO\Helper\AO. Essentially, the ObjectManager was resolving both of these references to the same class, but it only had type hints for one of the names so it didn't know what to provide to the incorrect one.

    A little help would have been nice, Magento! Maybe an error report that the requested class wasn't found? Still, at least this is finally over with.