Creating Custom Module for Magento 2

Prerequisites

To start with a Magento 2 module development, we want to give emphasis on two things:

1. Disable Magento cache
Firstly, to avoid manually flush the cache every time you make changes to your code, you should disable Magento cache during development.
The process is as usual: Admin → System → Cache Management → select all cache types and disable them.

2. Put Magento into a developer mode
Secondly, developer mode needs to be on to make sure that you catch all the errors Magento throws during the development.
From Magento 2 root. and through terminal, you should run the following command to begin the developer mode on:

Creating the module files and folders:

Download full module from our github

Module setup
In Magento 2 files are not distributed through the folders and have a modular structure. Here the modules are grouped by namespace and placed directly in the app/code folder. You can forget about code pools.
So our first step is to create the module folder and necessary files required to register a Magento module:

Create the following folders

Here, the Scriptlodge folder is the module’s namespace, and Helloworld is the module’s name.
Note: You will have to create it manually if you don’t have the code folder in your app directory.

Creating module.xml
Now in the module folder, we need to create a module.xml file in the app/code/Scriptlodge/Helloworld/etc folder with the following code:

Creating registration.php
With the following code you need create a registration.php file in the app/code/Scriptlodge/Helloworld folder to register the module:

At this stage, you need to clear Magento cache from admin, or through terminal from Magento 2 root with the following command:

Now the extension is supposed to start working. The presence of the module can be checked from Admin → Stores → Configuration → Advanced → Advanced
or you can open app/etc/config.php and check the array for the ‘Scriptlodge_Helloworld’ key, whose value should be set to 1:
module-install1

Creating router:

Basically two routers are needed to create, one for frontend and other for beckend/admin part.
The following routes.xml file is created for frontName and id setting to define queries for the extension.

1. Frontend router

The app/code/Scriptlodge/Helloworld/etc/frontend folder contains the following code for front-end:

Look the frontend router and route is defined with an id “helloworld”.

2. Backend/admin router
Similarly, the app/code/Scriptlodge/Helloworld/etc/adminhtml folder is used for backend:

Here the backend router and route is defined with an id “scriptlodge_helloworld”.

Creating a controller

The first part of the URL is generated from the frontName attribute.

Here you can see how the URLs are constructed in Magento 2:

So, the final URL will emerge in the following way:
helloworld/index/index

Now the Index.php controller file in the app/code/Scriptlodge/Helloworld/Controller/Index folder will have the following code:

Though in Magento 1 each controller can have multiple actions, in Magento 2 every action has its own class to implement the execute() method.

Creating a block:

To show something on the frontend, let’s create a block and a template for it.

Firstly, a Helloworld.php file in the app/code/Scriptlodge/Helloworld/Block folder with the following code will inherit from Magento class \Magento\Framework\View\Element\Template:

Creating a layout and template files:

Templates and layout files reside in view folder inside the module. So, we find three sub-folders under view:
a. adminhtml,
b. frontend,
c. base
And the above folders serve the following purposes respectively – adminhtml folder is used for admin, the frontend folder is used for frontend and the base folder is used for both, admin & frontend files.

Layout
First we will create a helloworld_index_index.xml file in the app/code/Scriptlodge/Helloworld/view/frontend/layout folder with the following code:

A block has been added to the content container in the layout and set the template of our block to helloworld.phtml, and the styles file to use when showing on frontend. The template and styles file has the following address:

Template
A helloworld.phtml file in the app/code/Scriptlodge/Helloworld/view/frontend/templates folder will have the following code:

Styles, Js and Images
And a hello.css file in the Scriptlodge\HelloWorld\view\frontend\web\css\hello.css.
In the same way, the images and js folders will reside into web folder.

Create admin settings:

To create some settings for the new extension it will be needed to add adminhtml folder to Scriptlodge\HelloWorld\etc folder. It will contain configuration files for backend.

Here, a routes.xml is needed for frontName and id setting, which is used to define queries for the extension. It was created in our previous section (Creating router).

The xml markup is slightly different in Magento 2 but in the previous version, they’re located in the system.xml file.

Here comes the two most popular settings as an example: a text setting and a yes/no setting.
Looking at the config file contents you can know what it actually means:

Add a new section to the settings block using . Set the unique ID and the name of the settings section inside. It is done because we have a very high possibility of using several apps from the same vendor on a single site.

Add the new

again, with the unique ID, and set the necessary parameters, such as type, translation fields, order, label, the block for which the section is added, and so on. And then add the settings just inside the section. They will be divided into groups (one group in our case). The groups are defined by , and the fields are set by . We have already created three settings and pointed out types, labels, visibility, translation, comments and the data model.

Let’s check the result. Open your Magento 2 backend, go to Stores – Configuration, we can see the settings!

module-config

Creating Helper:

Now we create the helper in the following path:

And we add \Magento\Framework\App\Config\ScopeConfigInterface interface object initialization to the helper, it works to receive the data from configuration.
Now the file looks like this:

Let’s use these functions in the block and the template, so we need to change block function and template:

Block file:

Template file:

Creating Model files:

Create installation script/Schema setup scripts
As in the 1.x versions of Magento, we need to create the installation file to use our own table.

In magento 2 schema setup scripts change database schema, they create or change needed database tables. If module is installing, Setup\InstallSchema::install() is executed.
The file should be created here: Scriptlodge\HelloWorld\Setup\InstallSchema.php

We can see that we are creating a “scriptlodge_helloworld” table with one field of integer type and four fields of text type.
Current module version is saved in setup_module table, which is equivalent of core_resource in Magento 1. Magento regulates what needs setup by comparing module versions with what it sees in that table.

Create Model

As in the Magento 1.x version, we need to create three classes to work with the model: the model itself, the resource model and the collection.

Let’s create a Scriptlodge\HelloWorld\Model\HelloWorld.php file and use the following initialization:

Create a Scriptlodge\HelloWorld\Model\ResourceModel\HelloWorld.php file and use the following initialization:

Create a Scriptlodge\HelloWorld\Model\ResourceModel\HelloWorld\Collection.php file and use the following initialization:

We just set the constructor for the model here. In fact, there is no great difference from the Magento1.x versions on this step.

Now we are going to check if the created model actually works. Create a simple function in the block we’re working with:

And also update Block __construct function,

Finally use these functions in the block and change the template file:

Finally deploy the module

module-data-view

Magento: Create or Update CMS Page & Static Block, Core Configuration, Product and Category information via Upgrade Scripts.

Why are upgrade scripts helpful

Running the upgrade scripts will automatically update the database when deploying your site to staging and production servers by hitting the url. This can help you to avoid manual setup changes in admin panel when releasing sites to different servers. It also helps us to keep track of all the changes we trigger in admin panel.

To run upgrade script, you need to create a custom module. Download full module from our github

In your module you create a file data-install-0.1.0.php

Update System Configuration:

CMS Static Blocks create or upgrade:

CMS Page Create or Upgrade:

Product Attributes Create or Upgrade:

Category Upgrade:

Update All Category and Run Indexing:

Product Upgrade:

Email Template Upgrade:

Drop table:

Magento: Wrong count in admin Grid when using GROUP BY clause

In Magento 1.x when you use GROUP BY clause in any Grid.php file in admin, the count always display wrong. Many times it displays 1 even if there are many records. Due to this your pagination also doesn’t work. This is a bug in Magento. Your getSize() always returns wrong count whereas total records in grid are proper.

To fix this, you need to edit one of your core file. As it’s not a good practice to edit core file, we will here override the core file. Overriding LIB module.

Copy Db.php file from magento / lib / Varien / Data / Collection / Db.php

Paste it to your local directory so the resultant folder structure would look like this:

magento / app / code / local / Varien / Data / Collection / Db.php

Now open this file to edit and replace getSelectCountSql function with below one

Difference between getsingleton() , getmodel() and getResourceModel() In Magento.

Mage::getSingleton()

Mage::getSingleton() will first check if the same class instance exists or not in the memory. If the instance exists then it will return the same object from the memory otherwise it load the model, save into Mage Register and return it. So Mage::getSingleton() is faster than Mage::getModel().

Example:

$product1 and $product2 both will share same memory of OS and return only one instance each time.

Now take a look at the getSingleton Method in Mage.php :

Mage::getModel()

Mage::getModel() will create a new instance of an object each time even such object exists in configuration.

Example

$product1 and $product2 both have different instant of same object and also occupy different memory.

Now take a look at the getModel Method in Mage.php:

Mage::getResourceModel()

All collections in Magento are resource models. They are instantiated by Mage::getResourceModel() or Mage::getModel()->getCollection(). It doesn’t really matter which function you use; the latter one simply calls the first one. The Magento team simply chose to make collections part of the resource, probably because collections need to query the database a lot. Usually, you will not have to call Mage::getResourceModel() for anything else than collections.

jQuery validationEngine Not Work with Bootstrap Select plugin

When bootstrap-select creates a cloned element, it uses an addClass call that copies the validate[.*] class into the new div element, and validationEngine tries to validate that.

I got a solution without modifying the core js file. For this we need to use validationEngine
“prettySelect”,”usePrefix” options, and we need to add “id” to cloned element and also need to removed the “validate[required]” class from this element. The full code look likes this.

It works for me. DEMO HERE : http://www.scriptlodge.com/code_demos/validationEngine/

How To Reset Admin Password in Magento ?

In this blog, I am showing how you can reset magento admin password if you lost it and cannot recover using Forgot Password option. I assume that you have the server access of magento i.e Database and FTP access.

For this you have to create a file named reseradminpass.php and paste the bellow code into this file and upload it in your magento root directory.

Here the variable $_HASH_SALT_LENGTH is for salting the password (set 32 for magento1.8 and magento1.9 and set 2 if your magento var is 1.7 or earlier).
Now browse the file as www.yourwebsite.com/reseradminpass.php. Hence, you can see the new password. So, copy it and replace the password field in “admin_user” table.

And that’s it, now you are able to login from admin using by this given password.

How do I add a static or dynamic block in Magento?

Magento provides an easy way to add blocks with using Layout-XML file and also call directly from the phtml file and added to any category page with no programming at all.

Adding Magento Static block:

from XML:

From phtml/php :

From the CMS page content/Shortcode way:

Adding Magento dynamic block:

From XML:

From the CMS page content/shortcode way:

From phtml/php:

or if the block is already existing in the layout you can get it by name:

Note that all functions available to you within the layout XML via are also available to call on any block in our code. For example, if we instantiated a new block to be added / appended to the head, we could execute something similar to this:

Call Magento Block method/function:

There are two syntax to call block method/function as below.

or

Example :

It shows the category menu.
or,

Adding Magento Content Blocks:
Add Handle in your local.xml/custommodule.xml so it looks like the following

We’re adding a new Block nested within our root. This is a Block that’s distributed with Magento, and will display a customer registration form. By nesting this Block within our root Block, we’ve made it available to be pulled into our simple_page.html Template. Next, we’ll use the Block’s getChildHtml method in our simple_page.phtml file.
Edit simple_page.html so it looks like this

Clear your Magento cache and reload the page and you should see the customer registration form.

Creating Custom Module in Magento

The first step is creating custom module in Magento is determining the namespace and module name. The namespace is simply an extra division that you can create you module in. This means that you can have two modules named the same thing if they are in two different namespaces. One way to use namespaces is to use your company name or initials for all of your modules.
Magento Modules follow a common naming scheme, Namespace_Module. This is very important to remember as you need to be careful about how you name your classes. Every custom module will be created in the directory:

Where to put our module?

All Magento modules are located in /app/code/ folder and are split into three groups, called code pools: core, community, local.

core – All original Magento modules are placed here. They provide base functionality of system and prototypes of blocks, models, helpers, controllers for further extending. The standard modules are: Mage_Core, Mage_Adminhtml, Mage_Catalog, Mage_Customer, Mage_Sales, Mage_Payment, Mage_Shipping etc. As you have probably noticed, all of them have prefix “Mage_”, we will talk about this a bit later. Unless you are sure about what you are doing (and even afterwards) never edit the code in the core modules.

community – As you can see from the name, this group dedicated for modules that are provided by 3rd party developers (i.e. not by Magento team). When you install this modules throught built-in installer (Magento Connect Manager) all of them will be put into the folder /app/code/community/.

local – This folder is created empty on a Magento installation. Or it can be absent in last versions 1.7.x of CMS, in this case you’ll have to create it manually. Folder /app/code/local/ is used for your custom modules. All development, generally, is performed here.
Except logical splitting modules into groups, this architecture allows us to override any module or separate class in “local” folder without editing original files, which is important for further update of Magento. If we look to the file /app/Mage.php, we’ll see this code:

So, if we have two files with the same name but in different code pools (for example, /core/Mage/Core/Model/Config.php and /local/Mage/Core/Model/Config.php), then file from local pool will be loaded.

Declare Your Magento Custom Module

Create app/etc/modules/Namespace_Module.xml and write below code.

Module Configuration:

Before that, we’ll need to setup a directory structure for the module. You won’t need all these directories, but there’s no harm in setting them all up now.

  • app/code/local/ CompanyName / ModuleName
  • app/code/local/ CompanyName / ModuleName/etc
  • app/code/local/ CompanyName / ModuleName/Block
  • app/code/local/ CompanyName / ModuleName/controllers
  • app/code/local/ CompanyName / ModuleName/Model
  • app/code/local/ CompanyName / ModuleName/Helper
  • app/code/local/ CompanyName / ModuleName/sql

Next, we will begin to configure our module. The configuration files belong inside our module in a directory named etc, so let’s create that along with a new XML file: app/code/local/ CompanyName /ModuleName /etc/config.xml. This XML file will inform Magento of the location of the files in our module, as well as many other things, such as version number and events to observe. For now, we will create a simple config.xml file, which contains comments that explain the meaning of each section.

Create Module Controller:

Now we will create controller app/code/local/Sl/Photogallery/controllers/IndexController.php

IndexController is called by default if we don’t call any other controller, as well as indexAction will be called by default if we don’t call any other action. As we can see, indexAction call only two methods ($this->loadLayout(),$this->renderLayout()) , that initialize and render website page.

Create Module Block:

Now we Create a Block class – app/code/local/Sl/Photogallery/Block/Photogallery.php

Frontend Layout configuration:

All templates and layout files are located in /app/design folder. Magento uses two design areas: “frontend” for public section and “adminhtml£ for backend.

Also there can be “install” area, which is used for installation pages. Themes are split into packages. By default there are two theme packages (base and default) in /app/design/frontend. If theme is not set in Magento configuration, default/default theme will be used by default. We are going to work with this theme.
Usually Magento theme consists of two main folders: “layout”, where layout configuration files are stored, and “template”, where all “.phtml” files are located. At first we need to create layout file /app/design/frontend/default/default/layout/photogallery.xml

Creating Model:

These are the initial steps that you need to follow when creating a model:

  • Create Model constructor class
  • Create Resource Model class
  • Create Model Collection class
  • Create Database table for model

To start with, within your node we need to declare the module version so that later we can create install/upgrade scripts.

Next we declare our model name within the node, which in this case be ‘Photogallery. Inside this we put our model class name which is simply the directory path to your model folder. We also specify our resource model name. After this we use our newly defined resource model name inside a self-titled node where we declare its class (again the file path), and database table name (which we’ll look at later).

The final bit of configuration we need to do is again in our node. When working with models, everything is pretty much scoped globally. We just need to make Magento aware if our install/upgrade scripts.

Creating Model/Photogallery.php class

This model initialisation class is as simple as it looks. From this point onwards we have a model type called ‘photogallery/photogallery’. Always extends the – Mage_Core_Model_Abstract class.

Creating Model/Resource/Photogallery.php class

We have now initialised our resource model, allowing our model to interact with the database. We simply pass in the model name and the database table primary key (which we haven’t created yet).

Creating Model/Resource/Photogallery/Collection.php class

We can now use our resource model to create the ability to grab a collection of our models, which we can do by simply initialising our collection class.

Creating Model/Resource/Setup.php Class

We start by creating a setup class so we can create an instance of the install object. We don’t need to change anything in the original core setup class so you can leave it blank.

Create installer file:

sql/photogallery_setup/install-0.1.0.php

Remember it’s good Magento practice to alias $this object to $installer. I’m gonna create a pretty basic table to demonstrate how it works.

Event Observer:

Event observers are extremely powerful and are one of the cleanest ways to extend Magento’s functionality without having to rewrite or override any core methods or classes. We want to observe the event that Magento dispatches just before the order is saved, so the code for the event we are interested in sales_order_place_before.

How do I find what events exist in Magento?

Figuring out how to find these events is relatively simple. We first need to know how Magento fires events and that is done like this:
Mage::dispatchEvent(‘event_name’, array(‘data’ => $data));

With that we can simply do a search in all of our files to return all the events. You can run this command on Linux/Mac:
grep -r “dispatchEvent(” /path/to/magento/install/)

We now need to modify our config.xml to include the event observer definition:

The above code is our basic config for our model. If you stick to similar naming conventions you’ll get on by fine here.
The main code I’d like to highlight here is contained between the tags. The first tag in represents our event we decided to use earlier on sales_order_place_before, so within here we are defining what to do when that event is fired. Within the tag we have the set up for our Observer. The value within represents the class name of our Observer, and then the value in is the method (or function) we will run when that event is fired.

Creating our Observer.php

Now we can create our Observer and place our code inside our method we will create. To do this create a file named Observer.php in app/code/local/Sl/Photogallery/Model and place the following code:

Cron Job:

Magento allows you to schedule custom tasks in an XML configuration, in a similar manner to the UNIX crontab style. Here we now need to modify our config.xml to include the crontab:

This example will run Sl_Photogallery_Model_Observer::notifynewPhotos method every day at 01:00am (0 1 * * *).
You can find detail about cron here

Finally our config.xml file looks like:

That’s it!!