ECommerce Insights Blog

Stay on top of it all and get ahead with useful articles, how-tos, tips and tricks on e-commerce.

How To Build A Magento2 Component From Scratch

How To Build A Magento2 Component From Scratch

If you looking to develop your own Magento 2 component you need to know the underlying structure very well. In this article, we will walk you through how to design, develop and deploy your own component for Magento2 Primarily we would talk about

  1. Underlying file structure
  2. Configuration files
  3. Required API services & interface
  4. Frontend design for the component

Before we begin any further let’s ensure the following prerequisites are met:

  1. You have a working Magento 2 installation up and running
  2. You have gone through Magento system requirement
  3. You have disabled the caching as suggested by Magento to set up the component file structure and adding configuration files

Magento 2 Components Development

  1. Creating a composer.json file
  2. Defining the configuration files used in the component
  3. Architecting the component’s file structure
  4. Registering the component
  5. URN Schema Validation of the component
  6. Naming the component
  7. Enabling/Disabling Magento2 Component
  8. Defining component’s load order

Now, lets dig deeper into each of the sections to define, design and develop a Magento2 component/module.

1. Creating a composer.json file for the component

This article assumes that you have the basic knowledge of installation and setting up a project using composer. You can download composer from here.

Pro Tip: Magento does not support path repository

Magento does not use global installed composer instead it looks for <Magento root>/vendor/ folder to determine the dependencies. Take a look at the following Magento2 composer.json files for versions, path, naming conventions and versioning information.

Defining the configuration files used in the component

Any Magento2 component has it’s own set of configuration files found under it’s /etc directory. Your module (depending on it’s nature) may have the following files

  • acl.xml
  • config.xml
  • di.xml
  • module.xml
  • webapi.xml

Keep in mind that Magento2 module also has nested configuration directories under /etc that may be required for frontend, html, SOAP or REST API specific configurations. Adding a configuration file config.xml under /etc/frontend will override whatever settings you have under /etc/config.xml.

Keep your global configuration files in that modules /etc directory of the component.

Keep configuration files under subdirectories so they are applicable only to their own functional areas.

Generate your configuration files as per your component’s requirements that describe what you intend to do with your module. e.g A module that requires a function under Admin or called in /etc/adminhtml needs to be defined like

  • <your module root dir>/etc/adminhtml/di.xml
  • <your module root dir>/etc/adminhtml/routes.xml

Modules that are supposed to do something with layout should add configuration files under  ~/etc/frontend/ e.g.

  • <your module root dir>/etc/frontend/.xml
  • <your module root dir>/etc/frontend/page_types.xml

Or if your module primarily focus on API calls should be placed under

  • <your module root dir>/etc/webapi_rest/di.xml
  • <your module root dir>/etc/webapi_soap/di.xml

It entirely depends on how you compartmentalize your configuration files either under top level of your module’s /etc directory or under nested directory for sanity.

3. Architecting the component’s file structure

One of the most important aspects of Magento 2 component development is how you will define and follow the file structure. Magento2 based on your configuration files will locate the required files under your components file structure. Missing any of these will break your module. Lets take a look at the file structure for 5 main elements

  1. Root Installation
  2. Required Files
  3. Module’s File Structure
  4.  Theme File Structure &
  5. Language Pack File Structure

Root Directory Location

A component’s root directory is the top-level directory for that component under which its folders and files are located. Depending on how your Magento development environment was installed, your component’s root directory can be located in two places:

  • <Magento install directory>/app: This is the recommended location for component development. You can easily set up this type of environment by Cloning the Magento 2 GitHub repository.
    • For modules, use app/code.
    • For storefront themes, use app/design/frontend.
    • For Admin themes, use app/design/adminhtml.
    • For language packages, use app/i18n.
  • <Magento install directory>/vendor: This location is found in the alternative setups where the composer create-project command was used to get a Magento 2 metapackage (which downloads the CE or EE code), or a compressed Magento 2 archive was extracted in order to install Magento.Any third party components (and the Magento application itself) are downloaded and stored under the vendor directory. If you are using Git to manage project, this directory is typically added to the .gitignore file.

Required files

Please note that following files are required for all components:

  • registration.php: specifies the directory in which the component is installed by vendors in production environments. By default, composer automatically installs components in the <Magento root dir>/vendor directory.
  • composer.json: Specifies component dependencies and other metadata.

Module file structure

Typically a module’s file structure should look like this

magento2-config-file-structure

Common Directories

Most common module directories which you are already familiar with

  • Block contains PHP view classes as part of Model View Controller(MVC) vertical implementation of module logic.
  • Controller contains PHP controller classes as part of MVC vertical implementation of module logic.
  • etc contains configuration files; in particular, module.xml, which is required.
  • Model contains PHP model classes as part of MVC vertical implementation of module logic.
  • Setup contains classes for module database structure and data setup which are invoked when installing or upgrading.

Additional Directories (Optional)

For plugins, layouts or localization additional folders can be introduced

  • Api contains any PHP classes exposed to the API.
  • i18n contains localization files.
  • Plugin contains any needed plugins.
  • view contains view files, design templates, static view files, email templates and layout files.

File Structure for Magento2 Themes

Following is how a theme file structure is supposed to look like

├── composer.json
├── etc
│   └── view.xml
├── i18n
│   └── en_US.csv
├── LICENSE_AFL.txt
├── LICENSE.txt
├── media
│   └── preview.jpg
├── registration.php
└── web
    ├── css
    │   ├── email.less
    │   ├── print.less
    │   ├── source
    │   │   ├── _actions-toolbar.less
    │   │   ├── _breadcrumbs.less
    │   │   ├── _buttons.less
    │   │   ├── components
    │   │   │   └── _modals_extend.less
    │   │   ├── _icons.less
    │   │   ├── _layout.less
    │   │   ├── _theme.less
    │   │   ├── _tooltips.less
    │   │   ├── _typography.less
    │   │   └── _variables.less
    │   ├── _styles.less
    │   ├── styles-l.less
    │   └── styles-m.less
    ├── images
    │   └── logo.svg
    └── js
        ├── navigation-menu.js
        ├── responsive.js
        └── theme.js

Common Directories

Typical theme directories are:

  • etc Contains configuration files such as the view.xml file which contains image configurations for all images and thumbnails.
  • i18n Translation dictionaries, if any.
  • media Theme preview images (screen capture of your theme) can be put in here.
  • web: Optional directory that contains static files organized into the following subdirectories:
    • css/source Contains a theme’s less configuration files that invoke mixins for global elements from the Magento UI library, and the theme.less file that overrides the default variables values.
    • css/source/lib Contains view files that override the UI library files stored in lib/web/css/source/lib.
    • fonts The folder to place the different fonts for your theme.
    • images Static images folder.
    • js The folder for your JavaScript files.

File Structure for Language Packs

A typical directory structure for three language packages follows:

├── de_DE
│   ├── composer.json
│   ├── language.xml
│   ├── LICENSE_AFL.txt
│   ├── LICENSE.txt
│   └── registration.php
├── en_US
│   ├── composer.json
│   ├── language.xml
│   ├── LICENSE_AFL.txt
│   ├── LICENSE.txt
│   └── registration.php
├── pt_BR
│   ├── composer.json
│   ├── language.xml
│   ├── LICENSE_AFL.txt
│   ├── LICENSE.txt
│   └── registration.php

Don’t forget to match the directory name with ISO code that helps Magento2 to identify the locale.

4. Registering the component

Magento2 requires each theme, module and language packs to register itself through Magento ComponentRegistrar class. Each such component MUST have registration.php in its root directory. As per component it’s registeration is performed through registration.php

Registering Modules in Magento2

This registers your module with the ComponentRegistrar

 ComponentRegistrar::register(ComponentRegistrar::MODULE, '<VendorName_ModuleName>', __DIR__);

VendorName name of the developer or their company
ModuleName name of the module.

Do not use “Ui” for your custom module name because the %Vendor%_Ui notation, required when specifying paths, might cause issues.

Usage

use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magik_ExtraFee', __DIR__);

Registering Themes in Magento2

This registers your theme with the ComponentRegistrar

 ComponentRegistrar::register(ComponentRegistrar::THEME, '<area>/<vendor>/<themename>', __DIR__);

area functional area
vendor name of the developer or company
theme name name of the theme.

Usage

 ComponentRegistrar::register(ComponentRegistrar::THEME, 'frontend/Magik/polo', __DIR__);

Registering Language Packs in Magento2

This registers your language packs with the ComponentRegistrar

 ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, '<VendorName>_<packageName>', __DIR__);

VendorName name of the developer or company
packageName name of the package

Usage

 ComponentRegistrar::register(ComponentRegistrar::LANGUAGE, 'magik_de_de', __DIR__);

Invoking Magento2 registration.php using Autoload in composer.json

You can simply invoke registration.php file in composer.json file’s autoload section like the following

 {
"name": "Magik/extra-fee",
"autoload": {
    "psr-4": { "Magik\\ExtraFee\\": "" },
    "files": [ "registration.php" ]
} }

registration.php file can have the following code

<?php
use \Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magik_ExtraFee', __DIR__);
?>

5. URN Schema Validation of the component

Magento uses Uniform Resource Names (URNs) to reference XML schema declarations as each Magento module can contain XSD files for SML validations. Primarily urn:magento supports

  • Module XSD
  • Framework XSD

Module XSD

The syntax for the module XSD is a colon separated declaration like

urn:magento:module:Magento_Flow:flows/content.xsd

  • urn:magento is the URN identifier
  • module is the reference type identifier
  • Magento_Flow is the name of the module. This must be exactly the same as the module specified by ComponentRegistrar in the registration.php file.
  • flows/content.xsd is the relative path to the module’s directory.

Framework XSD

The syntax for the framework XSD is a colon separated declaration. An example follows:

urn:magento:framework:Api/etc/extension_attributes.xsd

where

  • urn:magento is the URN identifier
  • framework is the reference type identifier. You can also add additional framework libraries as separate components with framework-<sub-name>
  • Api/etc/extension_attributes.xsd is the relative path to the framework’s directory.

Referencing a XSD from another XSD

Use URN notation to reference schema from inside a XSD document:

<xs:redefineschemaLocation="urn:magento:framework:Config/etc/view.xsd">

The URN resolution is invoked automatically by the libxml engine. Register the URN resolver by using libxml_set_external_entity_loader:

libxml_set_external_entity_loader(['Magento\Framework\Config\Dom\UrnResolver', 'registerEntityLoader']);

6. Naming the component

Pay special attention to naming your Module, here is how to properly name your component

Add the component’s module.xml file

Declare the component itself by adding a module.xml file in the /etc folder of your component. A component declares itself (that is, defines its name and existence) in the module.xml file, located in the Magento install directory at <ComponentName>/etc/.

The smallest working module.xml file would look something like this:

<?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="Vendor_ComponentName" setup_version="2.0.0"/>
</config>

Following information is required to name your component

name name of your component
setup_version module’s database schema version.

Add the components composer.json file

composer.json provides a component name and also specifies component dependencies. In addition, the Component Manager looks for a composer.json in a component’s root directory and can perform actions on the component and its dependencies.

In particular:

  • If a component has composer.json and the component was installed using Composer the Component Manager can update, uninstall, enable, or disable the component.
  • If the component has composer.json but was not installed using Composer Component Manager can still enable or disable the component.
  • We strongly recommend you include composer.json in your component’s root directory whether or not you intend to distribute it to other Magento merchants.

A sample follows:


{
    "name": "your-name/module-Acme",
    "description": "Test component for Magento 2",
    "require": {
        "php": "~5.5.0|~5.6.0",
        "magento/module-store": "1.0.0-beta",
        "magento/module-catalog": "1.0.0-beta",
        "magento/module-catalog-inventory": "1.0.0-beta",
        "magento/module-ui": "self.version",
        "magento/magento-composer-installer": "*"
    },
    "suggest": {
      "magento/module-webapi": "1.0.0-beta"
    },
    "type": "magento2-module",
     "version": "1.0.0-beta",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [ "registration.php" ],
        "psr-4": {
            "Magento\\CatalogImportExport\\": ""
        }
    }
    }

Note

  • name name of your component.
  • description  purpose of the component
  • require component dependencies
  • suggest oppotional dependencies
  • type defines component’s type i.e. magento2-theme, magento2-language, or magento2-module.
  • version release version
  • license license information
  • autoload instructions for composer to load the specified files.

7. Enabling/Disabling Magento2 Component

Enabling or disabling a Magento2 component is easy, you need to

  1. Disable the cache under System->Cache Management.
  2. Enter the following at the command line:
    bin/magento module:enable --clear-static-content Component_Name bin/magento setup:upgrade
  3. Check under Stores->Configuration->Advanced->Advanced that the component is present.

How To Disable a Magento2 Component

You can quickly disable a Magento2 component from command line. Type the following command

bin/magento module:disable --clear-static-content Component_Name

8. Defining Magento2 Component’s Load Order

Using <sequence> tag you can specify Magento2 component’s load order in it’s module.xml file. This ensures required dependencies are loaded before your component loads.

<sequence> declares the list of components that must be loaded before the current component is loaded. It’s used for loading different kind of files: configuration files, view files (including CSS, LESS, and template files), or setup classes. Note that <sequence> does not affect the loading of regular classes (non-setup classes).

I hope this is enough to get you started with a Magento2 component. Please let us know if you have any questions or face an issue implementing this.