Ajax search module for Magento

Monday, February 6, 2017

On 7:11 AM by Trọng Huỳnh Nguyễn   No comments
Magento 2 Create Payment Method proves that store admin has rights to generate as many payment methods as they need when your store is based on Magento 2 platform, an great era of ecommerce architecture. Depending on the customer’s requirement, you probably plug it in your list of the existing payment method. The additional payment methods surely bring the diversity of customer choice when they proceed to checkout on your site. On the other’s hands, multiple payment method is the great strategy to reach out the global marketplace.

In the tutorial, you will learn how to create own Payment Gateway integration in Magento 2 stores. After launching the new payment methods, you will find and configure it according the path Admin panel > Stores > Settings > Configuration > Sales > Payment Methods. There, admin possibly assigns a payment method to specific shipping method, this means they will work in pairs when enabling.

Step 1: Create payment method module

  1. Create file registration.php


  1. Declare 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="Mageplaza_Payment" setup_version="0.1.0">
<module name="Magento_Sales"/>
<module name="Magento_Payment"/>
<module name="Magento_Checkout"/>
<module name="Magento_Directory" />
<module name="Magento_Config" />

This module have to run after the Magento_Sales, Magento_Payment, Magento_Checkout, Magento_Directory, and Magento_Config. So we add depends (sequence) them like above block of code.

Step 2: Declare payment method module

  1. Now we create file payment.xml file in etc folder etc/payment.xml

<?xml version="1.0" ?>
<payment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<group id="offline">
<label>Offline Payment Methods</label>
<method name="simple">

  1. Create config.xml file in etc folder.

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

In this file, we declare Model of this payment method, we calle Simple model.
  1. Create Simple model file

Create file Model/Payment/Simple.php

namespace Mageplaza\Payment\Model\Payment;
class Simple extends \Magento\Payment\Model\Method\Cc
InfoInterface $payment
* @param float $amount
* @return $this
* @throws \Magento\Framework\Exception\LocalizedException
* @api
* @SuppressWarnings(PHPMD.UnusedFormalParameter)

public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)

if (!$this->canRefund())
throw new \Magento\Framework\Exception\LocalizedException(__("The refund action is not available."));

return $this;

This model includes basic functions such as - authorize(): Authorize the payment e.g: card - capture(): Capture money from a customer - refund(): Chargeback money to the customer.

Step 3: Display payment method in checkout page

In previous steps, we talked about declare module, config and model files. Now we need to display this Simple payment method in checkout page.
  1. Create layout file: view/frontend/layout/checkout_index_index.xml

<?xml version="1.0" ?>
<pagepage layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<referenceBlock name="checkout.root">
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="renders" xsi:type="array">
<item name="children" xsi:type="array">
<item name="offline-payments" xsi:type="array">
<item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/offline-payments</item>
<item name="methods" xsi:type="array">
<item name="simple" xsi:type="array">
<item name="isBillingAddressRequired" xsi:type="boolean">true</item>

  1. Create js files to load KO template in checkout page

function (Component,
"use strict";

type: "simple",
component: "Mageplaza_Payment/js/view/payment/method-renderer/simple-method"

return Component.extend();


In this file, it call another component: js/view/payment/method-renderer/simple-method

Now we need to create /view/frontend/web/js/view/payment/method-renderer/simple-method.js

function (Component)
"use strict";
return Component.extend(
template: "Mageplaza_Payment/payment/simple"
getMailingAddress: function ()
return window.checkoutConfig.payment.checkmo.mailingAddress;


  1. Finally, create KO template file /view/frontend/web/template/payment/simple.html

<div class="payment-method" data-bind="css: "_active": (getCode() == isChecked())">
<div class="payment-method-title field choice">
<input type="radio"
data-bind="attr: "id": getCode(), value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
<label data-bind="attr: "for": getCode()" class="label"><span data-bind="text: getTitle()"></span></label>
<div class="payment-method-content">
<!-- ko foreach: getRegion("messages") -->
<!-- ko template: getTemplate() --><!-- /ko -->
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion("before-place-order") -->
<!-- ko template: getTemplate() --><!-- /ko -->
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
click: placeOrder,
attr: title: $t("Place Order"),
css: disabled: !isPlaceOrderActionAllowed(),
enable: (getCode() == isChecked())

<span data-bind="i18n: "Place Order""></span>

You maybe also interested in Magento 2 Create Shipping Methods to custom the shipping methods as expected.


Saturday, February 4, 2017

On 11:54 PM by Trọng Huỳnh Nguyễn   No comments
Using VirtualType in Magento 2 is really necessary when you are running an virtual store based on Magento 2 platform? On Magento 2 platform, the di.xml supports for two types of node which are a node type and a node virtualtype, meanwhile virtualtype is considered as a perfect method instead of the type. The virtual tape allows inserting different dependencies into the existing classes but not making any change to other classes. With this tutorial, Mageplaza team will lead you to learn how to create and use VirtualType in Magento 2.

Creating VirtualType in Magento 2

Creating virtualtype in Magneto 2 means creating a sub-class for an existing class. All are available to help you create the virtualtype in magento 2.

class OurVirtualTypeName extends \Mageplaza\HelloWorld\Model\Virtualtype

The following script code is inserted to the module’s di.xml to create a virtualtype in Magento 2.

#File: app/code/Mageplaza/HelloWorld/etc/di.xml
<!-- ... -->
<virtualType name="ourVirtualTypeName" type="Mageplaza\HelloWorld\Model\Virtualtype">

Namely, the nodes are placed under the main node and include two attributes: name and type. While the name attribute is mostly the universally special name of that node, the type attribute is the real PHP for the virtual type.

As you see, it is simple to give some descriptions about the virtual type. If you erase the cache and repeat the request, the output is still the same.

$ php bin/magento hw:tutorial-virtual-type
First, we"ll report on the Mageplaza\HelloWorld\Model\Example object
The Property $property_of_example_object
is an object
created with the class:

Next, we"re going to report on the Example object"s one property (an Virtualtype class)
The Property $property_of_argument1_object
is an object
created with the class:

Finally, we"ll report on an Virtualtype object, instantiated separate from Example
The Property $property_of_argument1_object
is an object
created with the class:

Using Virtual Type in Magento 2

The functionality of a virtual type is replacing the position of PHP classes and you wouldn’t have to use a configuration as the below if you wanted to custom the argument injected into the Example class’s constructor.

#File: app/code/Mageplaza/HelloWorld/etc/di.xml 
<!-- ... -->
<virtualType name="ourVirtualTypeName" type="Mageplaza\HelloWorld\Model\Virtualtype">

<type name="Mageplaza\HelloWorld\Model\Example">
<argument name="the_object" xsi:type="object">Some\Other\Class</argument>


However, applying that command will lead you to the following error even though you have already cleaned your cache.

$ php bin/magento hw:tutorial-virtual-type

Class Some\Other\Class does not exist

Let’s move to a smart way with the virtual type. This means Some\Other\Class is recovered by ourVirtualTypeName. You can ensure that no error is caused unless you call the command with the above in place.

#File: app/code/Mageplaza/HelloWorld/etc/di.xml 
<!-- ... -->
<virtualType name="ourVirtualTypeName" type="Mageplaza\HelloWorld\Model\Virtualtype">

<type name="Mageplaza\HelloWorld\Model\Example">
<argument name="the_object" xsi:type="object">ourVirtualTypeName</argument>


Thanks for your reading and I hope that your business become more perfect with our guides of creating and using virtual types.

On 12:43 PM by Trọng Huỳnh Nguyễn   No comments
Creating composer.json in Magento 2 brings you more and more convenience to manage components better that used in your project. This topic is the well-documented instruction to assist the store owners to be familiar with the composer.json file.

Overview of Magento 2 Composer

Composer is a dependency management for PHP and in Magento 2, the composer plays the role in gathering components and product editions. When using the Magento 2 composer, there is no requirement of storing all code of each component, and you only need to create composer.json file and declare the needed components in that file instead that. Immediately, the composer will auto-define and take the corresponding data of those components to run for your project.

Here are some situations of the Magento 2 components including composer.json file:
  • When a component contains composer.json file, and needs to install via magneto 2 composer as well (like from Packagist, the Magento Marketplace, or another source), the Component Manager can update, uninstall, enable, or disable the component.

  • When a component still includes composer.json file but doesn’t need to install via Magento 2 composer such as the customization of written codes by a developer, the Component Manager can still enable or disable the component.

So, it is easier for you to run the project smoothly when your component’s root directory is added the composer.json file.

Explanation of composer.json files

Both Magento 2 components and product editions can work with composer.json files, specifically:


  • Location: composer.json

  • Name: magento/magento2ce

  • Type: project

This is the main composer.json file. It can be used as a template for every root composer.json file to call dependencies on third-party components.

CE project

  • Location: composer.json

  • Name: magento/project-community-edition

  • Type: project

This file is used for the Magento Community Edition project. It allows calling the dependencies on the Magento product and the class autoloader. In addition, you can use it to deploy Magento using Composer via Magento system integrators.

CE product

  • Location: composer.json

  • Name: magento/product-community-edition

  • Type: metapackage

This file is used for the Magento Community Edition product. It allows calling the dependencies on the Magento components (modules, themes, and so on) and third-party components. In addition, you can use it to deploy Magento using Composer via Magento system integrators.

Magento Framework

  • Location: lib/internal/Magento/Framework/composer.json

  • Name: magento/framework

  • Type: magento2-library

You only used this file for Magento framework.


  • Locations:


  • Name: <vendor-name>/<package-name>

  • Type: magento2-module

The composer.json file will aid a module extension to call external dependencies when it needs to be functioned.


  • Locations:


  • Name: <vendor-name>/<package-name>

  • Type: magento2-theme

For a theme component, this file consists of parent theme dependencies which are used for the inheritance of the extension.

Language Package

  • Location: app/i18n/<vendor-name>/<language-code>/composer.json

  • Name: <vendor-name>/<package-name>

  • Type: magento2-language

The composer.json file for language packages have to include the correct ISO code that is suitable for the language code.

Kinds of the component in Magento 2 Composer

There are many kinds of Magento 2 component like a module, theme, or language package. However in the case of not being assigning to an exact category, that will be called generally as magento-2-component.

To determine the type of Magento 2 component, the system possibly combines the directories and files to the correct locations, that is based on the Magento 2 directory structure.

Naming conventions of the component in Magento 2 Composer

When creating Magneto 2 composer, you are compulsory to use the format of the namespace: <vendor-name>/<package-name>. Thus, in this part, we will learn the conventions of the vendor-name and package-name.


The vendor-name must be lowercase as the following format for Magento 2 extensions: magento2/*

In case that you want to submit the extension to Magento Marketplace, you have to use the name you have registered the account there. That name is injected into the composer.json file as the vendor-name part of the extension name. I have a specific illustrator for your approach:

"name": "mageplaza/magento-2-seo-extension",
"description": "Magento 2 SEO extension",
"require": ~7.0.0",
"mageplaza/core-m2": "dev-master"
"type": "magento2-module",
"version": "1.1.1",
"license": [
"authors": [

"name": "Mageplaza",
"email": "hi@mageplaza.com",
"homepage": "https://www.mageplaza.com",
"role": "Leader"

"files": [
"Mageplaza\\Seo\\": ""


The package-name also contains the lowercase with multiple words, so Magento 2 Composer asks for separating them by dash as the following convention:


In particular, type-prefix is a type of Magento 2 component and suffix is a thing to realize which component it is within that type.

That is all things you need to pay attention when creating a composer.json file in Magento 2. Please follow carefully and make yourself more comfortable with the composer.json file when running your projects.


Friday, February 3, 2017

On 10:14 PM by Trọng Huỳnh Nguyễn   2 comments
Magento 2 URL Rewrite programmatically is one of the awesome solutions for online retailers as you who want to really create a huge number of the traffics of your website. The purpose of rewriting the url is allowing you generating 301 redirects into Magento 2 by the programmatical way.

What is URL Redirect?

URL redirect is a popular term in SEO and it is used for navigating the visitors to any link store owners expect. There are two main type of redirect: 301 redirect and 302 redirect. Therefore, if you are wondering how to continue working with the existing visitor at the current site while you are planning to build a new site with more efficiencies, the best answer is creating the search redirection through the redirect 301.

Overview of Magento 2 URL Rewrite programmatically

  • Step 1 : Generate constructor file

  • Step 2 : Insert custom URL rewrite in execute method

Step 1 : Generate constructor file

* @var \Magento\UrlRewrite\Model\ResourceModel\UrlRewriteFactory
protected $_urlRewriteFactory;

* @param Context $context
* @param \Magento\UrlRewrite\Model\ResourceModel\UrlRewriteFactory $urlRewriteFactory
public function __construct(
Context $context,
\Magento\UrlRewrite\Model\ResourceModel\UrlRewriteFactory $urlRewriteFactory
$this->_eavAttributeFactory = $eavAttributeFactory;

Step 2 : Insert custom URL rewrite in execute method

Only if your original website is www.example.com/customModule/customController/customAction, you want to rewrite the URL by www.example.com/xyz, instead. Then you can run the following method:

$urlRewriteModel = $this->_urlRewriteFactory->create()
/* set current store id */
/* this url is not created by system so set as 0 */
/* unique identifier - set random unique value to id path */
$urlRewriteModel->setIdPath(rand(1, 100000));
/* set actual url path to target path field */
/* set requested path which you want to create */
/* set current store id */


On 8:53 PM by Trọng Huỳnh Nguyễn   No comments
Magento 2 registry is the next topic Mageplaza wants to introduce in the series of this module development. Magento 1, as well as Magento 2, authorize you to register global variable that supports the static registry method.

To implement that, maybe you used to work with Mage::register() and Mage::registry() in Magento 1, but now in Magento 2 platform, there is a difference in running the registry. You will be required to apply \Magento\Framework\Registry, that accepts the settings and the registry of the restored data. However, first of all, you need to learn how to create or use the own custom registry and also show you how to retrieve global Magento 2 registry objects like current product, category, cms page, cms block, etc.

And that is lucky because all of them will be referred here. The topic today will help you be familiar with Magento 2 registry objects.

Please follow the following code snippet:

How to get and set custom attribute in registry / register

* @var \Magento\Framework\Registry

protected $_registry;

* ...
* ...
* @param \Magento\Framework\Registry $registry,
public function __construct(
\Magento\Framework\Registry $registry,
$this->_registry = $registry;

* Setting custom variable in registry to be used

public function setCustomVariable()

$this->registry->register("custom_var", "Added Value");

* Retrieving custom variable from registry
* @return string
public function getCustomVariable()

return $this->registry->registry("custom_var");

How to get registry of current Product, Category, CMS Page

* @var \Magento\Framework\Registry

protected $_registry;

* ...
* ...
* @param \Magento\Framework\Registry $registry,
public function __construct(
\Magento\Framework\Registry $registry,
$this->_registry = $registry;

* Return catalog product object
* @return \Magento\Catalog\Model\Product

public function getProduct()

return $this->_registry->registry("current_product");

* Return catalog current category object
* @return \Magento\Catalog\Model\Category

public function getCurrentCategory()

return $this->_registry->registry("current_category");

* Return catalog current cms page object
public function getCurrentCategory()

return $this->_registry->registry("current_cms_page");

With this instruction, you can achieve the best results of Magento 2 registry. Thanks for your watching and hope you are happy with it.

Happy coding!

On 7:53 PM by Trọng Huỳnh Nguyễn   No comments
Enabling and Disabling module is the popular operations when you run third-party modules on your Magento 2 store. The third-party modules are often the plugins you want to enable with the main purpose to improve the status of your online business. However, due to any reason that sometime causes the conflict when you activate all modules at the same time, it is necessary to disable the module that is not temporarily important.

So as to enable or disable, you can go into the configuration of that module, but on the topic today, Mageplaza will recommend you how to enable or disable Magento 2 module manually? That maybe will be great for the developers.

Overview of enabling/ disabling Magento 2 module

  • Step 1: Login to Magento File System

  • Step 2: Run Magento commands

  • Step 3: Enable/ Disable Magento 2 module

  • Step 4: Update the database of Magento 2 enabled module

Step 1: Login to Magento File System

Firstly, it is required to login to Magento File System as an owner who has rights to write and edit the file system in Magento. In a case you use the bash shell, running the following command will help you access Magento File System as the owner

su <Magento file system owner> -s /bin/bash -c

If Magento File System does not accept any external login, please use the command below:

sudo -u <Magento file system owner>

Step 2: Run Magento commands

To run Magento commands from any directory, add <your Magento install dir>/bin to your system PATH.

Please inject <your Magento install dir>/bin to your system PATH or follow this intructions:
  • cd <your Magento install dir>/bin and run them as ./magento <command name>

  • php <your Magento install dir>/bin/magento <command name>

<your Magento install dir> is a subdirectory of your web server’s docroot.

Step 3: Enable/ Disable Magento 2 module

Next, you can start to enable or disable the modules in Magento 2 as the following:

Run the commands

magento module:enable [-c|--clear-static-content] [-f|--force] [--all] <module-list> 
magento module:disable [-c|--clear-static-content] [-f|--force] [--all] <module-list>

With these commands, you need to understand:
  • <module-list> is the modules list that you want to enable or disable. If including the special characters, that module’s name will be put in either single or double quotes.

  • --all mentions you can simultaneously enable or disable all modules.

  • -f or --force means you obligate to enable or disable the modules regardless the dependencies.

  • -c or --clear-static-content means clear any published static view files. However, if there are many files having the same name, you will not eliminate all of them. That means there is more than one file named logo.gif and that will cause the mistake to display the file.

Show the list of the enabled and disabled modules with the command:

magento module:status

For example, you call Wee module that is disabled, need to run

magento module:disable Magento_Weee

Step 4: Update the database of Magento 2 enabled module

After enabling one or more modules, should declare the following command to request the update of the database:

magento setup:upgrade

Notes of enabling and disabling Magento 2 module

Here are some notes for you when you enable or disable the module which has the dependencies on another module.
  • If Module A depends on Module B:
    • It is required to disable Module A before disabling Module B.

    • It is required to enable Module B before enabling Module A if both are unavailable.

  • If Module A conflicts with Module B, you can disable both of them or do that individually, but especially, you cannot enable both at the same time.

The dependencies are announced in the require field in the Magento’s composer.json file of each module while the conflicts are announced in the conflict field. If there are the dependencies among the modules, and you still try to enable and disable without the rule, the error message will be shown and inform you the dependency graph.
  • A->B means Module A depends on Module B.

  • A->B->C means Module A depends Module B while Module B depends on Module C.

On 5:46 AM by Trọng Huỳnh Nguyễn   No comments

Similarly to the creating a new customers in Magento 2, online store owners can create product programmatically by implementing with the code instead of that you must waste time adding the new products through admin control. Today, on the topic Magento 2 create product programmatically will show you a code snippet that allows doing the creating many types of product (simple, configurable, and downloadable) perfectly.

To create Simple product programmatically

$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); // instance of object manager
$product = $objectManager->create("\Magento\Catalog\Model\Product");
$product->setSku("my-sku"); // Set your sku here
$product->setName("Sample Simple Product"); // Name of Product
$product->setAttributeSetId(4); // Attribute set id
$product->setStatus(1); // Status on product enabled/ disabled 1/0
$product->setWeight(10); // weight of product
$product->setVisibility(4); // visibilty of product (catalog / search / catalog, search / Not visible individually)
$product->setTaxClassId(0); // Tax class id
$product->setTypeId("simple"); // type of product (simple/virtual/downloadable/configurable)
$product->setPrice(100); // price of product
"use_config_manage_stock" => 0,
"manage_stock" => 1,
"is_in_stock" => 1,
"qty" => 999999999

Add an image to product

You can add multiple images into media gallary of this product.

// Adding Image to product
$imagePath = "sample.jpg"; // path of the image
$product->addImageToMediaGallery($imagePath, array("image", "small_image", "thumbnail"), false, false);

## Add custom options to the product
This can be applied for other product type such as Virtual, Downloadable Product, etc.

// Adding Custom option to product
$options = array(
"sort_order" => 1,
"title" => "Custom Option 1",
"price_type" => "fixed",
"price" => "10",
"type" => "field",
"is_require" => 0
"sort_order" => 2,
"title" => "Custom Option 2",
"price_type" => "fixed",
"price" => "20",
"type" => "field",
"is_require" => 0
foreach ($options as $arrayOption)
$option = $objectManager->create("\Magento\Catalog\Model\Product\Option")

With this script code, you should take some notes to create simple, configurable, downloadable products as the following:
  • To create the simple product, you need to pass the weight setting.

  • To create the configurable product, it is required to combine between associated products current product.

  • To create the downloadable product, it is required to insert the download link into the current product. If not, you will generate virtual or simple product.

How to assign associated products

This is a tip to help you create configurable products. Please using the snippet below:

$productId = 12; // Configurable Product Id
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->create("Magento\Catalog\Model\Product")->load($productId); // Load Configurable Product
$attributeModel = $objectManager->create("Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute");
$position = 0;
$attributes = array(134, 135); // Super Attribute Ids Used To Create Configurable Product
$associatedProductIds = array(2,4,5,6); //Product Ids Of Associated Products
foreach ($attributes as $attributeId)
$data = array("attribute_id" => $attributeId, "product_id" => $productId, "position" => $position);

$product->setTypeId("configurable"); // Setting Product Type As Configurable
$objectManager->create("Magento\ConfigurableProduct\Model\Product\Type\Configurable")->setUsedProductAttributeIds($attributes, $product);
$product->setNewVariationsAttributeSetId(4); // Setting Attribute Set Id
$product->setAssociatedProductIds($associatedProductIds);// Setting Associated Products

If there is the same assignment (the associated product is already assigned to configurable product), the command will run error.


Thursday, February 2, 2017

On 7:29 AM by Trọng Huỳnh Nguyễn   No comments

In Magento 2, apart from creating product and customer programmatically, you can also create invoice programmatically with ease when following the given guides in the Magento 2 create invoice programmatically topic.

Why do Magento 2 stores need to set up the program for creating the invoice? As you know, each time an invoice is created, that means an order is placed successfully and at the same time, Magento will notify you have earned the amount of money from the customer. However, by such normal way, you will get mass notifications from Magento 2 system as well as create the equivalent number of the invoices if your customer implements partial payment within the order. Therefore, this topic is the great solution to form the invoice while there is no dependency on the total paid of order.

Mageplaza brings you two simple steps for that and here you are!

Overview of creating invoice programmatically in Magento 2

  • Step 1: Declare event sales_order_invoice_pay

  • Step 2: Setup the observer class

Step 1: Declare event sales_order_invoice_pay

Start the settings with events.xml file in your custom module: /app/code/Mageplaza/HelloWorld/etc/events.xml

<?xml version="1.0"?>
<event name="sales_order_invoice_pay">
<observer name="webpos_sales_order_invoice_pay" instance="Mageplaza\HelloWorld\Observer\SalesOrderInvoicePay" />

Step 2: Setup the observer class


namespace Mageplaza\HelloWorld\Observer\Sales;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
class SalesOrderInvoicePay implements ObserverInterface

* @param EventObserver $observer
* @return $this
public function execute(EventObserver $observer)

$invoice = $observer->getEvent()->getInvoice();
$order = $invoice->getOrder();

/* reset total_paid & base_total_paid of order */
$order->setTotalPaid($order->getTotalPaid() - $invoice->getGrandTotal());
$order->setBaseTotalPaid($order->getBaseTotalPaid() - $invoice->getBaseGrandTotal());

On 7:17 AM by Trọng Huỳnh Nguyễn   No comments
Joining 2 tables in Magento 2 is the usual operation you need to implement when working with Magento 2 project. In order to make you do that with ease, the developer team from Mageplaza recommend the topic “Join Data Between 2 Tables in Magento 2”. In this topic, I will guide you how to get all orders that created with a specify payment method such as “Check Money Order”.

Overview of joining data between 2 tables in Magento 2

  • Step 1: Set a Collection class that extends

  • Step 2: Set your own function to get data

  • Step 3: Get the collection and call to filterOrder function above

  • Step 4: Save

Step 1: Set a Collection class

In the first step, you will form the Collection class that extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection

class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection

In the Collection class, there are two parameters you need to understand:
  • The first is your module name

  • The second is Sale order resource model from Magento sales module

 protected function _construct()

$this->_init("Mageplaza\HelloWorld\Model\YourModel", "Magento\Sales\Model\ResourceModel\Order");

Step 2: Set your own function to get data

Use the code script to set the own function, then get data as need.

protected function filterOrder($payment_method)

$this-&gt;sales_order_table = "main_table";
$this-&gt;sales_order_payment_table = $this-&gt;getTable("sales_order_payment");
-&gt;join(array("payment" =&gt; $this-&gt;sales_order_payment_table), $this-&gt;sales_order_table . ".entity_id= payment.parent_id",
array("payment_method" =&gt; "payment.method",

"order_id" =&gt; $this-&gt;sales_order_table.".entity_id"


Step 3: Get the collection and call to filterOrder function above

In your model, you just need to get the collection and call to filterOrder function above.

$collection = $this-&gt;YourCollectionFactory-&gt;create();


foreach ($collection as $item)
//do what you want with the data here.

Step 4: Save

Finally, Save all to complete with the joining data between 2 tables in Magento 2.

That’s all for you. Thanks for your reading!

On 4:38 AM by Trọng Huỳnh Nguyễn   No comments

What is UI Bookmark Component?

UI Bookmark Component is one of the Listing/Grid Secondary Component when you are working with Magento 2. UI Bookmark Component Magento 2 is in charge of storing all active and changed states of data grids. The bookmark component will cover some of the data including state of filters, columns position, applied sorting, pagination, and so on.

Field nameTypeDescription
bookmark_idint(10)Bookmark identifier
user_idint(10)User Id
namespacevarchar(255)Bookmark namespace
(UX1) identifiervarchar(255)Bookmark identifier
currentsmallint(6)Mark current bookmark per user, namespace and identifier
titlevarchar(255)Bookmark title
configlongtextBookmark config (JSON config for Js Bookmark component)
created_atdatetimeBookmark created at time
updated_atdatetimeBookmark updated at time

What is UI Bookmark Component structure

In UI Bookmark Component, you will get the structure as the following:
  • Collection of bookmarks located at app\code\Magento\Ui\view\base\web\js\grid\controls\bookmarks\bookmarks.js

    Template for collection at app\code\Magento\Ui\view\base\web\templates\grid\controls\bookmarks\bookmarks.html

  • Child elements which represent a separate view located at app\code\Magento\Ui\view\base\web\js\grid\controls\bookmarks\view.js

    Template for child element at app\code\Magento\Ui\view\base\web\templates\grid\controls\bookmarks\view.html

The bookmarks component activate app\code\Magento\Ui\view\base\web\js\grid\controls\bookmarks\storage.jscustom data storage to save bookmark state externally. After that, you can get the bookmarks on any device and in any browser.

How to add a UI Bookmark Component

The UI Bookmark Component comes with options as the below:
  • template option

  • component option

component: "Magento_Ui/js/grid/controls/bookmarks/view"
template: "path/to/template"
label: "New View",
index: "$ Date.now() "

  • storageConfig option

saveUrl: "path/to/save",
deleteUrl: "path/to/delete",
namespace: "namespace"