Magento 2 eBook - Development Cookbook EBook

Image Description

Brian Tran

The Most Popular Extension Builder for Magento 2

With a big catalog of 234+ extensions for your online store

CREDITS

  • Magento expert: Brian Tran
  • Editor: Tracy Vu.
  • Assistant Editor: Linda Thompson.
  • Design: Sam Thomas.
  • Special thanks to: LiLy White, Brian Tran.
  • Also thanks to Mageplaza team who supported a lot in the release of this special Module Development ebook for Magento 2.

Copyright © 2016 by Mageplaza.

Texts by kind permission of the authors.

Pictures by kind permission of the holders of the picture rights.

All rights reserved.

Magento 2 Module development or Magento 2 Hello World module trends is increase rapidly while Magento release official version. That why we - Mageplaza - are wring about a topic that introduces how to create a simple Hello World module in Magento 2. As you know, the module is a directory that contains blocks, controllers, models, helper, etc - that are related to a specific business feature. In Magento 2 modules will be live in app/code directory of a Magento installation, with this format: app/code/<Vendor>/<ModuleName>. Now we will follow this steps to create a simple module which work on Magento 2 and display Hello World.

Magento 2 Hello World module by Mageplaza.com

  • Step 1: Create a directory for the module like above format.
  • Step 2: Declare module by using configuration file module.xml
  • Step 3: Register module by registration.php
  • Step 4: Enable the module
  • Step 5: Create a Routers for the module.
  • Step 6: Create controller and action.

Step 1. Create a directory for the module like above format.

In this module, we will use Mageplaza for Vendor name and HelloWorld for ModuleName. So we need to make this folder: app/code/Mageplaza/HelloWorld

Step 2. Declare module by using configuration file module.xml

Magento 2 looks for configuration information for each module in that module’s etc directory. We need to create folder etc and add module.xml:

app/code/Mageplaza/HelloWorld/etc/module.xml

And the content for this 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="Mageplaza_HelloWorld" setup_version="1.0.0" />
</config>

In this file, we register a module with name Mageplaza_HelloWorld and the version is 1.0.0.

Step 3. Register module by registration.php

All Magento 2 module must be registered in the Magento system through the magento ComponentRegistrar class. This file will be placed in module root directory. In this step, we need to create this file:

app/code/Mageplaza/HelloWorld/registration.php

And it’s content for our module is:

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

Step 4. Enable the module

By finish above step, you have created an empty module. Now we will enable it in Magento environment. Before enable the module, we must check to make sure Magento has recognize our module or not by enter the following at the command line:

php bin/magento module:status

If you follow above step, you will see this in the result:

List of disabled modules:
Mageplaza_HelloWorld

This means the module has recognized by the system but it is still disabled. Run this command to enable it:

php bin/magento module:enable Mageplaza_HelloWorld

The module has enabled successfully if you saw this result:

The following modules has been enabled:
- Mageplaza_HelloWorld

This’s the first time you enable this module so Magento require to check and upgrade module database. We need to run this comment:

php bin/magento setup:upgrade

Now you can check under Stores -> Configuration -> Advanced -> Advanced that the module is present.

Step 5. Create a Routers for the module.

In the Magento system, a request URL has the following format:

http://example.com/<router_name>/<controller_name>/<action_name>

The Router is used to assign a URL to a corresponding controller and action. In this module, we need to create a route for frontend area. So we need to add this file:

app/code/Mageplaza/HelloWorld/etc/frontend/routes.xml

And content for this file:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="mageplaza" frontName="helloworld">
            <module name="Mageplaza_HelloWorld" />
        </route>
    </router>
</config>

After define the route, the URL path to our module will be: http://example.com/helloworld/*

Step 6. Create controller and action.

In this step, we will create controller and action to display Hello World. Now we will choose the url for this action. Let assume that the url will be: http://example.com/helloworld/index/display

So the file we need to create is:

app/code/Mageplaza/HelloWorld/Controller/Index/Display.php

And we will put this content:

<?php
namespace Mageplaza\HelloWorld\Controller\Index;

class Display extends \Magento\Framework\App\Action\Action
{
  public function __construct(
\Magento\Framework\App\Action\Context $context)
  {
    return parent::__construct($context);
  }

  public function execute()
  {
    echo 'Hello World';
    exit;
  }
}

If you have followed all above steps, you will see Hello World when open the url http://example.com/helloworld/index/display

In this topic Magento 2 Create: Block, Layouts, Templates we will learn about View in Magento 2 including Block, Layouts and Templates. In previous topic, we discussed about CRUD Models . As you know, a View will be use to output representation of the page. In Magento 2, View is built by three path: block, layout and template. We will find how it work by building the simple module Hello World using View path.

To create view in Magento 2

  • Step 1: Call view in controller
  • Step 2: Declare layout file
  • Step 3: Create block
  • Step 4. Create template file

Step 1: Call view in controller

In the previous Hello World Module topic, we have build a simple module and show the Hello World message on the screen directly by controller. Now we will edit it to call view to render page.

#file: app/code/Mageplaza/HelloWorld/Controller/Index/Display.php
<?php
namespace Mageplaza\HelloWorld\Controller\Index;

class Display extends \Magento\Framework\App\Action\Action
{
  protected $_pageFactory;
  public function __construct(
    \Magento\Framework\App\Action\Context $context,
    \Magento\Framework\View\Result\PageFactory $pageFactory)
  {
    $this->_pageFactory = $pageFactory;
    return parent::__construct($context);
  }

  public function execute()
  {
    return $this->_pageFactory->create();
  }
}

We have to declare the PageFactory and create it in execute method to render view.

Step 2: Declare layout file

The Layout is the major path of view layer in Magento 2 module. The layout file is a XML file which will define the page structure and will be locate in {module_root}/view/{area}/layout/ folder. The Area path can be frontend or adminhtml which define where the layout will be applied.

There is a special layout file name default.xml which will be applied for all the page in it’s area. Otherwhile, the layout file will have name as format: {router_id}_{controller_name}_{action_name}.xml.

You can understand the layout in detail in this Magento topic , and the instruction of a layout structure.

When rendering page, Magento will check the layout file to find the handle for the page and then load Block and Template. We will create a layout handle file for this module:

#file: app/code/Mageplaza/HelloWorld/view/frontend/layout/helloworld_index_display.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <referenceContainer name="content">
        <block class="Mageplaza\HelloWorld\Block\Display" name="helloworld_display" template="Mageplaza_HelloWorld::sayhello.phtml" />
    </referenceContainer>
</page>

In this file, we define the block and template for this page:

Block class: Mageplaza\HelloWorld\Block\Display Template file: Mageplaza_HelloWorld::sayhello.phtml

Step 3: Create block

The Block file should contain all the view logic required, it should not contain any kind of html or css. Block file are supposed to have all application view logic.

Create a file:

app/code/Mageplaza/HelloWorld/Block/Display.php

The Block for this module:

<?php
namespace Mageplaza\HelloWorld\Block;
class Display extends \Magento\Framework\View\Element\Template
{
  public function __construct(\Magento\Framework\View\Element\Template\Context $context)
  {
    parent::__construct($context);
  }

  public function sayHello()
  {
    return __('Hello World');
  }
}

Every block in Magento 2 must extend from Magento\Framework\View\Element\Template. In this block we will define a method sayHello() to show the word “Hello World”. We will use it in template file.

Step 4. Create template file

Create a template file call sayhello.phtml

app/code/Mageplaza/HelloWorld/view/frontend/templates/sayhello.phtml

Insert the following code:

<?php
echo $block->sayHello();

In the layout file, we define the template by Mageplaza_HelloWorld::sayhello.phtml. It mean that Magento will find the file name sayhello.phtml in templates folder of module Mageplaza_HelloWorld. The template folder of the module is app/code/{vendor_name}/{module_name}/view/frontend/templates/.

In the template file, we can use the variable $block for the block object. As you see, we call the method sayHello() in Block. It’s done, please access to this page again (http://example.com/helloworld/index/display) and see the result.

Controller specially is one of the important thing in Magento 2 module development, and PHP MVC Framework in general. It functionarity is that received request, process and render page.

In Magento 2 Controller has one or more files in Controller folder of module, it includes actions of class which contain execute() method. There are 2 different controllers, they are frontend controller and backend controller. They are generally similar of workflow, but admin controller is a little different. There is a checking permission method in admin controller. Let’s take an example:

protected function _isAllowed()
{
    return $this->_authorization->isAllowed('Magento_AdminNotification::show_list');
}

It will check the current user has right to access this action or not.

How controller work?

It receive an request from end-user (browser or comamnd line), for example:

http://example.com/route_name/controller/action
  • route_name is a unique name which is set in routes.xml.
  • controller is the folder inside Controller folder.
  • action is a class with execute method to process request.

One of the important in Magento system is frontController (Magento\Framework\App\FrontController), it alway receive request then route controller, action by route_name Let take an example of routing an request:

foreach ($this->_routerList as $router) {
   try {
      $actionInstance = $router->match($request);
   …
}

If there is an action of controller class found, execute() method will be run.

How to create a controller?

To create a controller, we need to create a folder inside Controller folder of module and declare an action class inside it. For example, we create a Test controller and a Hello action for module Mageplaza_HelloWorld:

app/code/Mageplaza/HelloWorld/Controller/Test/SayHello.php

And content of this file should be:

namespace Mageplaza\HelloWorld\Controller\Test;
class SayHello extends \Magento\Framework\App\Action\Action
{
  public function execute()
  {
    echo 'Hello World! Welcome to Mageplaza.com';
    exit;
  }
}

As you see, all controller must extend from \Magento\Framework\App\Action\Action class which has dispatch method which will call execute method in action class. In this execute() method, we will write all of our controller logic and will return response for the request.

Forward and redirect in action.

\Magento\Framework\App\Action\Action class provide us 2 important methods: _forward and _redirect.

Forward method

_forward() protected function will edit the request to transfer it to another controller/action class. This will not change the request url. For example, we have 2 actions Forward and Hello World like this:

namespace Mageplaza\HelloWorld\Controller\Test;
class Forward extends \Magento\Framework\App\Action\Action
{
  public function execute()
  {
    $this->_forward('hello');
  }
}

If you make a request to http://example.com/route_name/test/forward , here are result will be displied on the screen.

Hello World! Welcome to Mageplaza.com

You can also change the controller, module and set param for the request when forward. Please check the _forward() function for more information:

protected function _forward($action, $controller = null, $module = null, array $params = null)
{
    $request = $this->getRequest();

    $request->initForward();

    if (isset($params)) {
        $request->setParams($params);
    }

    if (isset($controller)) {
        $request->setControllerName($controller);

        // Module should only be reset if controller has been specified
        if (isset($module)) {
            $request->setModuleName($module);
        }
    }

    $request->setActionName($action);
    $request->setDispatched(false);
}

Redirect method

This method will transfer to another controller/action class and also change the response header and the request url. With above example, if we replace _forward() method by this _redirect() method:

  $this->_redirect('*/*/hello');

Then after access from the url http://example.com/route_name/test/forward, the url will be change to http://example.com/route_name/test/hello and show the message Hello World! Welcome to Mageplaza.com on the screen.

How to rewrite controller in Magento 2

To rewrite controller, you can do it by using preference. It mean that you need to put a rule in your router config using before attribute.

Open Mageplaza/HelloWorld/etc/di.xml insert the following block of code inside <config> tag rewrite controller in Magento 2

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">

<router id="standard">
    <route id="mageplaza" frontName="hello">
       <module name="Mageplaza_HelloWorld" before="Magento_Customer" />
    </route>
</router>

</config>

This will completely change controller/action of module Magento_Customer with your controller code, so you should extend rewrite controller and make a change on the function which you want. Also, the controller and action in your module must have same name with rewrite controller/action. For example, if you want to rewrite controller: Magento\Customer\Controller\Account\Create.php

You have to register a router like above and create a controller:

NameSpace\ModuleName\Controller\Account\Create.php

Content of Create.php file:

namespace Mageplaza\HelloWorld\Controller\Account;

use Magento\Customer\Model\Registration;
use Magento\Customer\Model\Session;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\App\Action\Context;

class Create extends \Magento\Customer\Controller\AbstractAccount
{
    /** @var Registration */
    protected $registration;

    /**
     * @var Session
     */
    protected $session;

    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param Context $context
     * @param Session $customerSession
     * @param PageFactory $resultPageFactory
     * @param Registration $registration
     */
    public function __construct(
        Context $context,
        Session $customerSession,
        PageFactory $resultPageFactory,
        Registration $registration
    ) {
        $this->session = $customerSession;
        $this->resultPageFactory = $resultPageFactory;
        $this->registration = $registration;
        parent::__construct($context);
    }

    /**
     * Customer register form page
     *
     * @return \Magento\Framework\Controller\Result\Redirect|\Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        if ($this->session->isLoggedIn() || !$this->registration->isAllowed()) {
            /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */
            $resultRedirect = $this->resultRedirectFactory->create();
            $resultRedirect->setPath('*/*');
            return $resultRedirect;
        }

        /** @var \Magento\Framework\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        return $resultPage;
    }
}

CRUD Models in Magento 2 can manage data in database easily, you don’t need to write many line of code to create a CRUD. CRUD is stand for Create, Read, Update and Delete. We will learn about some main contents: How to setup Database, Model, Resource Model and Resource Magento 2 Get Collection and do database related operations. In previous topic, we discussed about Creating Hello World Module

Before learning this topic, let’s decide how the table which we work with will look. I will create a table mageplaza_topic and take the following columns:

  • topic_id - the topic unique identifier
  • title - the title of the topic
  • content - the content of the topic
  • creation_time - the date created

To create Model in Magento 2

  • Step 1: Setup Script
  • Step 2: Model
  • Step 3: Resource Model
  • Step 4: Resource Model Collection
  • Step 5: Factory Object

Step 1: Setup Script

Firstly, we will create database table for our CRUD models. To do this we need to insert the setup file:

app/code/Mageplaza/HelloWorld/Setup/InstallSchema.php

This file will execute only one time when install the module. Let put this content for this file to create above table:

namespace Mageplaza\HelloWorld\Setup;
class InstallSchema implements \Magento\Framework\Setup\InstallSchemaInterface
{
    public function install(
        \Magento\Framework\Setup\SchemaSetupInterface $setup,
        \Magento\Framework\Setup\ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        $table = $installer->getConnection()->newTable(
            $installer->getTable('mageplaza_topic')
        )->addColumn(
            'topic_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['identity' => true, 'nullable' => false, 'primary' => true, 'unsigned' => true],
            'Topic ID'
        )->addColumn(
            'title',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Topic Title'
        )->addColumn(
            'content',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            '2M',
            [],
            'Topic Content'
        )->addColumn(
            'creation_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
            'Topic Creation Time'
        )->setComment(
            'Mageplaza Topic Table'
        );
        $installer->getConnection()->createTable($table);
        $installer->endSetup();
    }
}

This content is showing how the table created, you can edit it to make your own table. Please note that Magento will automatically run this file for the first time when installing the module. If you installed the module before, you will need to upgrade module and write the table create code to the UpgradeSchema.php in that folder.

After this please run this command line:

php bin/magento setup:upgrade

Now checking your database, you will see a table with name ‘mageplaza_topic’ and above columns. If this table is not created, it may be because you ran the above command line before you add content to InstallSchema.php. To fix this, you need remove the information that let Magento know your module has installed in the system. Please open the table ‘setup_module’, find and remove a row has module equals to ‘mageplaza_topic’. After this, run the command again to install the table.

This InstallSchema.php is used to create database structure. If you want to install the data to the table which you was created, you need to use InstallData.php file:

app/code/Mageplaza/HelloWorld/Setup/InstallData.php

Please take a look in some InstallData file in Magento to know how to use it. This’s some file you can see:

- vendor/magento/module-tax/Setup/InstallData.php
- vendor/magento/module-customer/Setup/InstallData.php
- vendor/magento/module-catalog/Setup/InstallData.php

As I said above, those install file will be used for first time install the module. If you want to change the database when upgrade module, please try to use UpgradeSchema.php and UpgradeData.php.

Step 2: Model

Model is a huge path of MVC architecture. In Magento 2 CRUD, models have many different functions such as manage data, install or upgrade module. In this tutorial, I only talk about data management CRUD. We have to create Model, Resource Model, Resource Model Conllection to manage data in table: mageplaza_topic as I mentioned above.

Before create model, we need to create the interface for it. Let create the TopicInterface:

app/code/Mageplaza/HelloWorld/Model/Api/Data/TopicInterface.php

And put this content:

<?php
namespace Mageplaza\HelloWorld\Model\Api\Data;
interface TopicInterface
{
  public function getId();
  public function setId();
  
  public function getTitle();
  public function setTitle();
  
  public function getContent();
  public function setContent();
  
  public function getCreationTime();
  public function setCreationTime();
}

This interface has defined the set and get method to table data which we would use when interacting with the model. This interface plays an important role when it comes time to exporting CRUD models to Magento service contracts based API.

Now we will create the model file:

app/code/Mageplaza/HelloWorld/Model/Topic.php

And this is the content of that file:

<?php 
namespace Mageplaza\HelloWorld\Model;
class Topic extends \Magento\Framework\Model\AbstractModel implements \Magento\Framework\DataObject\IdentityInterface,
\Mageplaza\HelloWorld\Model\Api\Data\TopicInterface
{
  const CACHE_TAG = 'mageplaza_topic';

  protected function _construct()
  {
    $this->_init('Mageplaza\HelloWorld\Model\ResourceModel\Topic');
  }

  public function getIdentities()
  {
    return [self::CACHE_TAG . '_' . $this->getId()];
  }
}

This model class will extends AbstractModel class Magento\Framework\Model\AbstractModel and implements TopicInterface and IdentityInterface \Magento\Framework\DataObject\IdentityInterface. The IdentityInterface will force Model class define the getIdentities() method which will return a unique id for the model. You must only use this interface if your model required cache refresh after database operation and render information to the frontend page.

The _construct() method will be called whenever a model is instantiated. Every CRUD model have to use the _construct() method to call _init() method. This _init() method will define the resource model which will actually fetch the information from the database. As above, we define the resource model Mageplaza\Topic\Model\ResourceModel\Topic The last thing about model is some variable which you should you in your model:

  • $_eventPrefix - a prefix for events to be triggered
  • $_eventObject - a object name when access in event
  • $_cacheTag - a unique identifier for use within caching

Step 3: Resource Model

As you know, the model file contain overall database logic, it do not execute sql queries. The resource model will do that. Now we will create the Resource Model for this table: Mageplaza\HelloWorld\Model\ResourceModel\Topic

Content for this file:

<?php
namespace Mageplaza\HelloWorld\Model\ResourceModel;
class Topic extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
{
  protected function _construct()
  {
    $this->_init('mageplaza_topic', 'topic_id');
  }
}

Every CRUD resource model in Magento must extends abstract class \Magento\Framework\Model\ResourceModel\Db\AbstractDb which contain the functions for fetching information from database.

Like model class, this resource model class will have required method _construct(). This method will call _init() function to define the table name and primary key for that table. In this example, we have table ‘mageplaza_topic’ and the primary key ‘topic_id’.

Step 4: Resource Model Collection - Get Model Collection

The collection model is considered a resource model which allow us to filter and fetch a collection table data. The collection model will be placed in:

Mageplaza\HelloWorld\Model\ResourceModel\Topic\Collection.php

The content for this file:

<?php
namespace Mageplaza\HelloWorld\Model\ResourceModel\Topic;
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
  protected function _construct()
  {
    $this->_init('Mageplaza\HelloWorld\Model\Topic', 'Mageplaza\HelloWorld\Model\ResourceModel\Topic');
  }
}

The CRUD collection class must extends from \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection and call the _init() method to init the model, resource model in _construct() function.

Step 5: Factory Object

We are done with creating the database table, CRUD model, resource model and collection. So how to use them?

In this part, we will talk about Factory Object for model. As you know in OOP, a factory method will be used to instantiate an object. In Magento, the Factory Object do the same thing.

The Factory class name is the name of Model class and append with the ‘Factory’ word. So for our example, we will have TopicFactory class. You must not create this class. Magento will create it for you. Whenever Magento’s object manager encounters a class name that ends in the word ‘Factory’, it will automatically generate the Factory class in the var/generation folder if the class does not already exist. You will see the factory class in

var/generation/<vendor_name>/<module_name>/Model/ClassFactory.php

To instantiate a model object we will use automatic constructor dependency injection to inject a factory object, then use factory object to instantiate the model object.

For example, we will call the model to get data in Block. We will create a Topic block:

Mageplaza\HelloWorld\Block\Topic.php

Content for this file:

<?php
namespace Mageplaza\HelloWorld\Block;
class Topic extends \Magento\Framework\View\Element\Template
{
  protected $_topicFactory;
  public function _construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Mageplaza\HelloWorld\Model\TopicFactory $topicFactory
  ){
    $this->_topicFactory = $topicFactory;
    parent::_construct($context);
  }

  public function _prepareLayout()
  {
    $topic = $this->_topicFactory->create();
    $collection = $topic->getCollection();
    foreach($collection as $item){
      var_dump($item->getData());
    }
    exit;
  }
}

As you see in this block, the TopicFactory object will be created in the _construct() function. In the _prepareLayout() function, we use $topic = $this->_topicFactory->create(); to create the model object.

People also searched for:

  • magento 2 CRUD
  • magento 2 model
  • magento 2 create model
  • create Model in Magento 2
  • how to create Model in Magento 2
  • magento 2 get collection
  • magento 2 model get collection
Magento Support
& Maintenance Services

Make sure your M2 store is not only in good shape but also thriving with a professional team yet at an affordable price.

Get Started
avada marketing automation

People also searched for

Subscribe

Stay in the know

Get special offers on the latest news from Mageplaza.

Earn $10 in reward now!

Earn $10 in reward now!

comment
iphone
go up