Create a module

A module is a structural element of Commerce—modules form the backbone of the system. You typically start a customization by building a module.

Who is this video for?

  • Backend developers

Steps to add a module

  1. Create the module folder.
  2. Create the etc/module.xml file.
  3. Create the registration.php file.
  4. Run bin/magento setup:upgrade to register and install the module.
  5. Check that the module is working.

The module.xml file

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Training_Sales">
        <sequence>
            <module name="Magento_Sales"/>
        </sequence>
    </module>
</config>

The registration.php file

<?php

use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
    ComponentRegistrar::MODULE,
    'Training_Sales',
    __DIR__);

Add a plugin

Next, you add functionality to your basic module. You use plugins as essential tools in Adobe Commerce development. This video and tutorial show you how to create a plugin.

Things to remember for plugins

  • You declare all plugins in di.xml.
  • You give each plugin a unique name.
  • You can optionally set the disabled and sortOrder attributes.
  • You set the plugin scope by choosing which folder contains the di.xml file.
  • You run plugins before, after, or around the target method call.
  • Avoid around plugins. They tempt you, but they often represent the wrong choice and cause performance issues.

Plugin code samples

The tutorial uses the following XML and PHP classes to add a plugin to your first module.

app/code/Training/Sales/etc/adminhtml/di.xml

<?xml version="1.0" ?>
<!--
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- A Plugin that executes when the admin user places an order -->
    <type name="Magento\Sales\Model\Order">
        <plugin name="admin-training-sales-add-logging" type="Training\Sales\Plugin\AdminAddLoggingAfterOrderPlacePlugin" disabled="false" sortOrder="0"/>
    </type>
</config>

app/code/Training/Sales/etc/frontend/di.xml

<?xml version="1.0" ?>
<!--
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- A plugin that executes when a customer uses the LoginPost controller from the Luma frontend -->
    <type name="Magento\Customer\Controller\Account\LoginPost">
        <plugin name="training-customer-loginpost-plugin"
                type="Training\Sales\Plugin\CustomerLoginPostPlugin" sortOrder="20"/>
    </type>
</config>

app/code/Training/Sales/etc/webapi_rest/di.xml

<?xml version="1.0" ?>
<!--
/**
 * Copyright &copy; Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- A plugin that executes when the REST API is used OR when the Luma frontend places an order -->
    <type name="Magento\Sales\Model\Order">
        <plugin name="rest-training-sales-add-logging" type="Training\Sales\Plugin\RestAddLoggingAfterOrderPlacePlugin"/>
    </type>
</config>

app/code/Training/Sales/Plugin/AdminAddLoggingAfterOrderPlacePlugin.php

<?php

declare(strict_types=1);

namespace Training\Sales\Plugin;

use Magento\Sales\Model\Order;
use Psr\Log\LoggerInterface;

/**
 *
 */
class AdminAddLoggingAfterOrderPlacePlugin
{

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

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

    /**
     * Add log after an order is placed
     *
     * @param Order $subject
     * @param Order $result
     * @return Order
     */
    public function afterPlace(Order $subject, Order $result): Order
    {
        // Log this admin area order
        $this->logger->notice('An ADMIN User placed an Order -

### app/code/Training/Sales/Plugin/CustomerLoginPostPlugin.php

```php
<?php

declare(strict_types=1);

namespace Training\Sales\Plugin;

use Psr\Log\LoggerInterface;
use Magento\Framework\App\RequestInterface;

/**
 * Introduces Context information for ActionInterface of Customer Action
 */
class CustomerLoginPostPlugin
{

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

    /**
     * @var RequestInterface
     */
    private RequestInterface $request;

    /**
     * @param LoggerInterface $logger
     * @param RequestInterface $request
     */
    public function __construct(LoggerInterface $logger, RequestInterface $request)
    {
        $this->logger = $logger;
        $this->request = $request;
    }

    /**
     * Simple example of a before Plugin on a public method in a Controller
     */
    public function beforeExecute()
    {
        $login = $this->request->getParam('login');
        $username = $login['username'];
        $this->logger->notice( "Login Post controller was used for " . $username );
    }
}

app/code/Training/Sales/Plugin/RestAddLoggingAfterOrderPlacePlugin.php

<?php

declare(strict_types=1);

namespace Training\Sales\Plugin;

use Magento\Sales\Model\Order;
use Psr\Log\LoggerInterface;

/**
 *
 */
class RestAddLoggingAfterOrderPlacePlugin
{

    /**
     * @var LoggerInterface
     */
    private LoggerInterface $logger;

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

    /**
     * Add log after an order is placed
     *
     * @param Order $subject
     * @param Order $result
     * @return Order
     */
    public function afterPlace(Order $subject, Order $result): Order
    {
        // Log this customer driven order
        $this->logger->notice('A Customer placed an Order for

## Useful resources

* [Module Reference guide](https://developer.adobe.com/commerce/php/module-reference/){target="_blank"}
* [Plugins](https://developer.adobe.com/commerce/php/development/components/plugins/){target="_blank"}

 . $subject->getBaseTotalDue());
        return $result;
    }
}

app/code/Training/Sales/Plugin/CustomerLoginPostPlugin.php

CODE_BLOCK_PLACEHOLDER_6

app/code/Training/Sales/Plugin/RestAddLoggingAfterOrderPlacePlugin.php

CODE_BLOCK_PLACEHOLDER_7

Useful resources

. $subject->getBaseTotalDue());
return $result;
}
}


## Useful resources

* [Module Reference guide](https://developer.adobe.com/commerce/php/module-reference/){target="_blank"}
* [Plugins](https://developer.adobe.com/commerce/php/development/components/plugins/){target="_blank"}

 . $subject->getBaseTotalDue());
        return $result;
    }
}

app/code/Training/Sales/Plugin/CustomerLoginPostPlugin.php

CODE_BLOCK_PLACEHOLDER_6

app/code/Training/Sales/Plugin/RestAddLoggingAfterOrderPlacePlugin.php

CODE_BLOCK_PLACEHOLDER_7

Useful resources

recommendation-more-help
commerce-learn-help-home