1

In magento, in every step of project you can find instances of interfaces, just like for example in this function below:

public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) 
{
        //Upgrade schema logic
}

How is it possible to create instance of interface, If I understand interfaces well, it's not possible to have interface object

SchemaSetupInterface $setup, 
ModuleContextInterface $context
Denis2310
  • 939
  • 1
  • 15
  • 41

1 Answers1

1

That is kind of good programming and in Magento it has something to do with its dependency injection (DI) pattern.

General Interface Usage

Interfaces defines a minimum of funkctions, a class has to implement. So if a function accepts an interface of type SchemaSetupInterface, it just wants a class which implements the functions defined in SchemaSetupInterface.

In this special case, where the interface is defined as follows, the upgrade function wants a class which implements getIdxName($tableName, $fields, $indexType = ''); and getFkName($priTableName, $priColumnName, $refTableName, $refColumnName);.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Framework\Setup;

/**
 * DB schema resource interface
 * @api
 * @since 100.0.2
 */
interface SchemaSetupInterface extends SetupInterface
{
    /**
     * Retrieves 32bit UNIQUE HASH for a Table index
     *
     * @param string $tableName
     * @param array|string $fields
     * @param string $indexType
     * @return string
     */
    public function getIdxName($tableName, $fields, $indexType = '');

    /**
     * Retrieves 32bit UNIQUE HASH for a Table foreign key
     *
     * @param string $priTableName  the target table name
     * @param string $priColumnName the target table column name
     * @param string $refTableName  the reference table name
     * @param string $refColumnName the reference table column name
     * @return string
     */
    public function getFkName($priTableName, $priColumnName, $refTableName, $refColumnName);
}

Magento DI.xml

Magento supports di.xml definition files and a global ObjectManager which resolves classes based on the preference configuration in the di.xmls. Instances of classes which implement special interfaces are then automatically injected into constructors of your classes.

Example: vendor/magento/magento2-base/app/etc/di.xml:

<config>
    <!-- ... more -->
    <preference for="\Magento\Framework\Setup\SchemaSetupInterface" type="\Magento\Setup\Module\Setup" />
    <!-- ... more -->
</config>

With this configuration, Magento passes an instance of \Magento\Setup\Module\Setup, which is defines as follows to your upgrade function.

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Setup\Module;

use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\App\ResourceConnection;

/**
 * @api
 */
class Setup extends \Magento\Framework\Module\Setup implements SchemaSetupInterface
{
    /**
     * Retrieve 32bit UNIQUE HASH for a Table index
     *
     * @param string $tableName
     * @param array|string $fields
     * @param string $indexType
     * @param string $connectionName
     * @return string
     */
    public function getIdxName(
        $tableName,
        $fields,
        $indexType = '',
        $connectionName = ResourceConnection::DEFAULT_CONNECTION
    ) {
        return $this->getConnection($connectionName)->getIndexName($this->getTable($tableName), $fields, $indexType);
    }

    /**
     * Retrieve 32bit UNIQUE HASH for a Table foreign key
     *
     * @param string $priTableName  the target table name
     * @param string $priColumnName the target table column name
     * @param string $refTableName  the reference table name
     * @param string $refColumnName the reference table column name
     * @param string $connectionName
     * @return string
     */
    public function getFkName(
        $priTableName,
        $priColumnName,
        $refTableName,
        $refColumnName,
        $connectionName = ResourceConnection::DEFAULT_CONNECTION
    ) {
        return $this->getConnection($connectionName)->getForeignKeyName(
            $this->getTable($priTableName),
            $priColumnName,
            $refTableName,
            $refColumnName
        );
    }
}

You can find more information about dependency injection in Magento in the Docs.

Felix
  • 2,531
  • 14
  • 25