Categories


Recent Posts


Archives


Watch out for Magento’s Generated Classes

astorm

Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento front end book you'll ever need. Get your copy today!

This one comes straight from my Patreon slack (where, despite not actively working with the Magento platform, I still advise, mentor, and be-a-therapist-for people who are — also while I’m pitching my Patreon slack to you I also still sell Commerce Bug and No Frills Magento 1/2 Layout, both of which will make you and your development teams a little less crazy on your Magento projects).

Magento’s automatic constructor dependency injection system includes features that will automatically generate certain types of classes for you if they don’t already exist.

Here’s an example from Magento’s source

public function __construct(
    ObjectManagerFactory $objectManagerFactory,
    \Magento\Indexer\Model\Indexer\CollectionFactory $collectionFactory = null
) {
    $this->objectManagerFactory = $objectManagerFactory;
    $this->collectionFactory = $collectionFactory;
    parent::__construct();
}

Look high and low, you won’t find a class file for Magento\Indexer\Model\Indexer\CollectionFactory anywhere in Magento’s source repo. That’s because Magento’s object manager generates this factory class on the fly and drops it in the generated folder.

#File: generated//code/Magento/Indexer/Model/Indexer/CollectionFactory.php
<?php
namespace Magento\Indexer\Model\Indexer;

/**
 * Factory class for @see \Magento\Indexer\Model\Indexer\Collection
 */
class CollectionFactory
{
    /**
     * Object Manager instance
     *
     * @var \Magento\Framework\ObjectManagerInterface
     */
    protected $_objectManager = null;

    /**
     * Instance name to create
     *
     * @var string
     */
    protected $_instanceName = null;

    /**
     * Factory constructor
     *
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     * @param string $instanceName
     */
    public function __construct(\Magento\Framework\ObjectManagerInterface $objectManager, $instanceName = '\\Magento\\Indexer\\Model\\Indexer\\Collection')
    {
        $this->_objectManager = $objectManager;
        $this->_instanceName = $instanceName;
    }

    /**
     * Create class instance with specified parameters
     *
     * @param array $data
     * @return \Magento\Indexer\Model\Indexer\Collection
     */
    public function create(array $data = [])
    {
        return $this->_objectManager->create($this->_instanceName, $data);
    }
}

The Magento dev docs describe the behavior of these factory classes. It’s a nice feature for people who live the Design Patterns lifestyle — lots of boilerplate code automatically generated for you and all your factories behave the same.

Or — all your factories could behave the same. The yak my patron was shaving turned out to be the fault of classes like this.

#File: vendor/magento//module-search/Model/Autocomplete/ItemFactory.php
<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

namespace Magento\Search\Model\Autocomplete;

use Magento\Framework\ObjectManagerInterface;

class ItemFactory
{
    /**
     * @var ObjectManagerInterface
     */
    private $objectManager;

    /**
     * @param ObjectManagerInterface $objectManager
     */
    public function __construct(
        ObjectManagerInterface $objectManager
    ) {
        $this->objectManager = $objectManager;
    }

    /**
     * @param array $data
     * @return Item
     */
    public function create(array $data)
    {
        return $this->objectManager->create(\Magento\Search\Model\Autocomplete\Item::class, ['data' => $data]);
    }
}

For — reasons? — Magento ships with a bunch of actual, non-generated factory classes. For — even more reasons? — some of these factories behave in ways that are subtly different from the generated classes, making it super easy to get tripped up by the behavior of a factory you didn’t write.

One more bit of unexploded ordinance you’ll need to be aware of if you’re doing any sort of non-trivial Magento 2 customizations.

Copyright © Alan Storm 1975 – 2019 All Rights Reserved

Originally Posted: 18th November 2019