4

In Magento 2, to my understanding, dependency for each interface should be declared somewhere in the di.xml files, either in app/etc/ or < module_dir >/etc/ or some deeper directories to override.

But when I was tracing the schema setup code, I couldn't seem to find the dependency relation anywhere.

For example:

    namespace Vendor\Mod\Setup;

    use Magento\Framework\Setup\InstallSchemaInterface;
    use Magento\Framework\Setup\ModuleContextInterface;
    use Magento\Framework\Setup\SchemaSetupInterface;
    use Magento\Framework\DB\Ddl\Table;

    class InstallSchema implements InstallSchemaInterface
    {
        /**
         * Installs DB schema for a module
         *
         * @param SchemaSetupInterface $setup
         * @param ModuleContextInterface $context
         * @return void
         */
        public function install(
             SchemaSetupInterface $setup,
             ModuleContextInterface $context)
        {
            ...
        }
    }

Though in the book it said:

"... Magento\Setup\Module\Setup is the one extending \Magento\Framework\Module\Setup and implementing SchemaSetupInterface."

it didn't help much to sort out my problem.

Also, I've noticed that components under Magento\Framework\ are not regular magento2-modules.(not sure if it makes any difference here.)

So, why is the DI declaration not needed in this case? How did magento know which implementation to use?

Thanks for the help.

2 Answers 2

3

In Magento 2, to my understanding, dependency for each interface should be declared somewhere in the di.xml files, either in app/etc/ or < module_dir >/etc/ or some deeper directories to override.

That understanding is incorrect. Here's a different way to think about things that might help you understand things a little better (and don't feel bad for not understanding -- this stuff is tricky if you don't have the right background)

An interface is a PHP feature. Programmer A can provide an interface so that programmer B can write classes that behave the same as programmer A's classes.

A "type hint" is another PHP feature, and is a way to define a function or method that forces programmers to pass certain sorts of objects in as a parameter. The following

use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface

public function install(
    \Magento\Framework\Setup\SchemaSetupInterface $setup,
    \Magento\Framework\Setup\ModuleContextInterface $context
)
{
    ...
}

says that when programmers call the install method

 $object->install($arg1, $arg2);

that $arg1 needs to be an object that implements the Magento\Framework\Setup\SchemaSetupInterface interface, and $arg2 needs to be an object that implements the Magento\Framework\Setup\SchemaSetupInterface. Type hints force other programmers to use your methods correctly, and not pass in some object that just happens to work.

So far this is all plain old PHP. The only special thing Magento does w/r/t to all this is in the __construct method of a class. If you create a class with the following constructor

public function __construct(\Foo\Bar\Baz $foo)
{

}

Magento 2 will automatically instantiate a \Foo\Bar\Baz object for you. Before Magento instantiates a \Foo\Bar\Baz object, if will look in di.xml. If it finds a configuration for \Foo\Bar\Baz in the merged di.xml tree, it will use that information when instantiating the object.

This means it's possible to use an interface as a type hint in a __construct method, and configure a class preference for that interface in a di.xml file, and have Magento instantiate the object configured in the di.xml file. So your original assumption might be better stated

If an interface is used as a automatic constructor dependency injection type hint, the concrete class to use for the injected object should be configured in the di.xml configuration tree.

So in your case, since you're looking at an interface in a method named install, di.xml doesn't come into play.

If your'e interested, I've got a pretty in depth tutorial series on how the object manager and di.xml work from top to bottom.

1
  • Thank you Alan! Looks like I've mistaken normal OO polymorphism concept for Magento's use of DI. Actually I've read your articles before xD I will study them again.( more closely this time!!)
    – Tienyi Chi
    Feb 6, 2016 at 9:15
0

Firstly, you need to consider, when do we need a di declaration: it is so that ObjectManager knows to create an object when we inject an interface in constructor. But in this case, SchemaSetupInterface is just a contract of how setup classes are to be structured, and is never injected into constructor, so OM doesn't need to know what is the concrete class.

How setup works

  • Collect all available modules and read their versions (setup_version) from configuration. Modules are read in the order of declared module dependencies.
  • For each module, if current version (schema_version in database) of the module is absent, first execute install method of InstallSchema setup class, and then upgrade method of UpgradeSchema setup class, if the classes exist.
  • For each module, if current version of the module is outdated, execute upgrade method of UpgradeSchema setup class, if the class exists.
  • For each module, check whether Recurring schema setup class exists and, if it does, execute install method of Recurring setup class. Fully initialize application.
  • Repeat the install/upgrade process with data setup classes for each new or updated module, in a similar fashion corresponding to schema setup process.

Secondly, you are right, component under Magento/Framework are not regular modules, they are libraries, so that all modules can use them.

Thirdly, setup is separate from both application in app/code as well as framework. This is intentional so that setup is not dependent on the application and vice-versa. Hence, setup kindof communicates with application via the library. Library specifies a contract for application to use, and setup uses this knowledge to access the required scripts. Please see https://github.com/magento/magento2/blob/develop/setup/src/Magento/Setup/Model/Installer.php#L1145

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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