39

Magento 2 contains a number of class files that are either pre-generated, or are generated on the fly. They live in

var/generated

These generated files include factory classes. From the documentation, it's my understanding that a programmer uses factory classes to instantiate "non-injectable" objects. A "non-injectable" object is an object that can't be added via __constructor dependency injection, usually because it requires user input to instantiate.

What's not clear from the documentation is how Magento 2 knows it needs to generate a factory class. This bit

If a non-existent factory is encountered by object manager in runtime mode or compiler, the object manager generates the factory.

makes it sound like if I use a factory class in the object manager (or, by extension, in the dependency injection __constructors), that Magento 2 will generate it for me. But how does the object manager know the thing I'm requesting is a factory?

Also, there seems to be two commands for automatically generating (or "compiling") all the generated classes. Running either of these commands generates a large number of Factory classes. What configuration and/or code files are these commands looking at to generate the needed factory objects?

I know that tracing the object manager and/or command code all the way down would reveal this, but I'm hoping to avoid that long and arduous journey.

21

Some interesting code location for how this all works together: https://github.com/magento/magento2/blob/develop/dev/tests/integration/testsuite/Magento/Framework/Code/GeneratorTest.php#L40

With the different types coming mostly from here https://github.com/magento/magento2/tree/develop/lib/internal/Magento/Framework/ObjectManager/Code/Generator but also from here https://github.com/magento/magento2/tree/develop/lib/internal/Magento/Framework/Interception/Code/Generator for the Interception code.

It is all triggered by the autoloader here https://github.com/magento/magento2/blob/develop/lib/internal/Magento/Framework/Code/Generator/Autoloader.php#L32

public function load($className)
{
    if (!class_exists($className)) {
        return Generator::GENERATION_ERROR != $this->_generator->generateClass($className);
    }
    return true;
}
9

I haven't found in the code, the conditions for which the factories are generated, but from my understanding a factory class is generated when it is requested and not found.
There are some reserved keywords Factory, Proxy, Interceptor, if used, will trigger code generation when the specific classes are not found.
I will post back as soon as I find the code that triggers the factory generation.
So, if you request the class Some\Namespace\HereFactory and the class does not exist, because it ends with the keyword Factory it will be generated in the var/generation/Some/Namespace/HereFactory.php

  • Looks like docs should be updated since ObjectManager isn't really the one generating. Special auto loader is part of the answer. github.com/magento/magento2/blob/develop/lib/internal/Magento/… – Chris O'Toole Jun 1 '15 at 0:17
  • 1
    That lines up with my experience (see gist.github.com/astorm/f245ce9c761c9a8053aa), but it does raise the question 1. Where does this happen in the object manager code (i.e. what's the actual convention) 2. How does the compiler/generator know what factories to generate? – Alan Storm Jun 1 '15 at 1:37
8

I am digging in this same pea soup right now. My understanding so far is that all of the stuff that gets auto generated at /var/generation is done from the preferences and interfaces declared in app/etc/di.xml.

Interfaces and preferences of yours are going to be declared in the di.xml file in your /app/code/Vendor/<module>/etc/di.xml.

It knows to generate the object(s) for you because you have declared an interface in your __constructor AND have declared a preference for that interface either globally or locally in the appropriate di.xml file.

I offer three grains of salt with my comments.

  • +1 for the useful information -- but it seems like Factories come from somewhere other than the di.xml files -- you can send something into the object manager that ends in Factory and it will generate a file for you. – Alan Storm May 31 '15 at 22:37
  • Does this help? bit.ly/1BOtdie – Steve Johnson Jun 5 '15 at 13:45

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.