Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

Magento 2 Tutorial: Building a Complete Module

Magento is currently the largest open-source eCommerce platform in the world. Due to its feature rich and extensible code base, merchants with large and small operations all around the world have been using it for a wide variety of projects.
Magento 1 has been around for eight years, and its successor, Magento 2, was released at the end of 2015, improving weak points of the earlier version such as:
  • Improved performance
  • Official automated test suite
  • Better back-end UI
  • New, more modern front-end codebase
  • A more modular way to develop modules, with files contained inside the Magento
  • code instead of being scattered all over the place
  • Reduced number of conflicts between modules trying to customize the same functionality
A little over one year down the road, and the improvement is visible, even though not all of the problems mentioned have been totally solved. Now it’s completely safe to say that Magento 2 is a much more robust piece of software than its predecessor. Some of the improvements present in Magento 2 are:
  • Unit and integration tests, including an official and documented way to create them for custom modules
  • Modules that are really modularized, having all of their files placed under one single directory
  • A richer templating system, allowing the theme developer to create an n-level template hierarchy
  • A series of useful design patterns adopted throughout the code, improving the code quality and decreasing probability of errors created by modules—These include automatic dependency injection, service contracts, repositories, and factories, to name a few.
  • Native integration to Varnish as a full page caching system, as well as Redis for session and cache handling
  • PHP 7 support
The learning curve for Magento 2, with all of these changes, has become even steeper. In this article, I intend to show you how to develop your first Magento 2 Module, and point you in the right direction to continue your studies. Let’s get to it!

Prerequisites

It is important that you have a good understanding of the following technologies/concepts in order to follow the rest of this article:
  • Object-oriented Programming (OOP)
  • PHP
  • Namespaces
  • MySQL
  • Basic bash usage
From all of the above, OOP is probably the most important one. Magento was initially created by a team of experienced Java developers, and their legacy can certainly be seen throughout the codebase. In case you are not very confident about your OOP skills, it might be a good idea to review it before beginning your work with the platform.

Overview of Magento 2’s Architecture

Magento’s architecture was designed with the intent of making the source code as modularized and extensible as possible. The end goal of that approach is to allow it to be easily adapted and customized according to each project’s needs.
Customizing usually means changing the behavior of the platform’s code. In the majority of systems, this means changing the “core” code. In Magento, if you are following best practices, this is something you can avoid most of the time, making it possible for a store to keep up to date with the latest security patches and feature releases in a reliable fashion.
Magento 2 is a Model View ViewModel (MVVM) system. While being closely related to its sibling Model View Controller (MVC), an MVVM architecture provides a more robust separation between the Model and the View layers. Below is an explanation of each of the layers of a MVVM system:
  • The Model holds the business logic of the application, and depends on an associated class—the ResourceModel—for database access. Models rely on service contracts to expose their functionality to the other layers of the application.
  • The View is the structure and layout of what a user sees on a screen – the actual HTML. This is achieved in the PHTML files distributed with modules. PHTML files are associated to each ViewModel in the Layout XML files, which would be referred to as binders in the MVVM dialect. The layout files might also assign JavaScript files to be used in the final page.
  • The ViewModel interacts with the Model layer, exposing only the necessary information to the View layer. In Magento 2, this is handled by the module’s Block classes. Note that this was usually part of the Controller role of an MVC system. On MVVM, the controller is only responsible for handling the user flow, meaning that it receives requests and either tells the system to render a view or to redirect the user to another route.
A Magento 2 module consists of some, if not all, elements of the architecture described above. The overall architecture is described below (source):
A Magento 2 module can in turn define external dependencies by using Composer, PHP’s dependency manager. In the diagram above, you see that the Magento 2 core modules depend on the Zend Framework, Symfony as well as other third-party libraries.
Below is the structure of Magento/Cms, a Magento 2 core module responsible for handling the creation of pages and static blocks.
Each folder holds one part of the architecture, as follows:
  • Api: Service contracts, defining service interfaces and data interfaces
  • Block: The ViewModels of our MVVM architecture
  • Controller: Controllers, responsible for handling the user’s flow while interacting with the system
  • etc: Configuration XML files—The module defines itself and its parts (routes, models, blocks, observers, and cron jobs) within this folder. The etc files can also be used by non-core modules to override the functionality of core modules.
  • Helper: Helper classes that hold code used in more than one application layer. For example, in the Cms module, helper classes are responsible for preparing HTML for presentation to the browser.
  • i18n: Holds internationalization CSV files, used for translation
  • Model: For Models and ResourceModels
  • Observer: Holds Observers, or Models which are “observing” system events. Usually, when such an event is fired, the observer instantiates a Model to handle the necessary business logic for such an event.
  • Setup: Migration classes, responsible for schema and data creation
  • Test: Unit tests
  • Ui: UI elements such as grids and forms used in the admin application
  • view: Layout (XML) files and template (PHTML) files for the front-end and admin application
It is also interesting to notice that, in practice, all of Magento 2’s inner workings live inside a module. In the image above, you can see, for instance, Magento_Checkout, responsible for the checkout process, and Magento_Catalog, responsible for the handling of products and categories. Basically, what this tells us is that learning how to work with modules is the most important part of becoming a Magento 2 developer.
All right, after this relatively brief introduction to the system architecture and module structure, let’s do something more concrete, shall we? Next, we will go through the traditional Weblog tutorial in order to get you comfortable with Magento 2 and on track to become a Magento 2 Developer. Before that, we need to set up a development environment. Let’s get to it!

Setting up the Development Environment

At the time of this writing, we were able to use the official Magento 2 DevBox, which is a Magento 2 Docker container. Docker on macOS is something I still consider to be unusable, at least with a system which heavily depends on fast disk I/O such as Magento 2. So, we will do it the traditional way: Install all packages natively on our own machine.

Setting up the Server

Installing everything surely is a bit more tedious, but the end result will be a lightning-fast development environment. Believe me, you will save hours of work by not depending on Docker for your Magento 2 development.
This tutorial assumes an environment on macOS with Brew installed on it. If that’s not the case for you, the basics will remain the same, changing only the way you install the packages. Let’s start with installing all of the packages:
brew install mysql nginxb php70 php70-imagick php70-intl php70-mcrypt
Then start the services:
brew services start mysql
brew services start php70
sudo brew services start nginx
Ok, now we’ll point a domain to our loopback address. Open the hosts file in any editor, but make sure you have superuser permissions. Doing that with Vim would be:
sudo vim /etc/hosts
Then add the following line:
127.0.0.1       magento2.dev
Now we’ll create a vhost in Nginx:
vim /usr/local/etc/nginx/sites-available/magento2dev.conf
Add the following content:
server {
listen 80;

server_name magento2.dev;

set $MAGE_ROOT /Users/yourusername/www/magento2dev;
set $MAGE_MODE developer;


# Default magento Nginx config starts below
root $MAGE_ROOT/pub;
index index.php;
autoindex off;
charset off;

add_header 'X-Content-Type-Options' 'nosniff';
add_header 'X-XSS-Protection' '1; mode=block';

location / {
try_files $uri $uri/ /index.php?$args;
}

location /pub {
location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) {
deny all;
}
alias $MAGE_ROOT/pub;
add_header X-Frame-Options "SAMEORIGIN";
}

location /static/ {
if ($MAGE_MODE = "production") {
expires max;
}

location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;

if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}

location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;

if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}

if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}

add_header X-Frame-Options "SAMEORIGIN";
}

location /media/ {
try_files $uri $uri/ /get.php?$args;

location ~ ^/media/theme_customization/.*\.xml {
deny all;
}

location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;
try_files $uri $uri/ /get.php?$args;
}

location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;
try_files $uri $uri/ /get.php?$args;
}

add_header X-Frame-Options "SAMEORIGIN";
}

location /media/customer/ {
deny all;
}

location /media/downloadable/ {
deny all;
}

location /media/import/ {
deny all;
}

location ~ /media/theme_customization/.*\.xml$ {
deny all;
}

location /errors/ {
try_files $uri =404;
}

location ~ ^/errors/.*\.(xml|phtml)$ {
deny all;
}

location ~ cron\.php {
deny all;
}

location ~ (index|get|static|report|404|503)\.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
fastcgi_param PHP_VALUE "memory_limit=768M \n max_execution_time=60";
fastcgi_read_timeout 60s;
fastcgi_connect_timeout 60s;
fastcgi_param MAGE_MODE $MAGE_MODE;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

# Default magento Nginx config finishes below

client_max_body_size 20M;
}
If you haven’t dealt with Nginx before, this file might scare you, so let us explain the little bits here, as it will also shed some light on some of Magento’s inner workings. The first lines simply tell Nginx that we are using the default HTTP port, and our domain is magento2.dev:
  listen 80;
server_name magento2.dev;
Then we set some environment variables. The first one—$MAGE_ROOT—holds the path to our codebase. Notice you will need to change the root path to match your username/folder path, wherever you plan to have the source placed on:
  set $MAGE_ROOT /Users/yourusername/www/magento2dev;
The second variable—$MAGE_MODE—sets the runtime mode for our shop. As we are developing a module, we will use the developer mode. This allows us to code faster, as we won’t have to compile or deploy static files while developing. The other modes are production and default. The real use for the latter is not yet clear.
  set $MAGE_MODE developer;
After this variables are set, we define the vhost root path. Notice that we suffix the 


This post first appeared on Latest Technology News And Trends, please read the originial post: here

Share the post

Magento 2 Tutorial: Building a Complete Module

×

Subscribe to Latest Technology News And Trends

Get updates delivered right to your inbox!

Thank you for your subscription

×