:::: MENU ::::
Posts tagged with: admin controller

Magento 2 reset admin password

Today we discuss how in Magento 2 reset admin password. This topic include how to reset admin password with sql query, reset password through command line interface (cli). Sometime you forgot the admin password so today we discuss how to reset your admin password. There are two ways to do that. First go to database and reset your with sql query and second create new user from command line and then login and reset the password from admin panel.

Reset with Query

Change test123 to your required password.

UPDATE `admin_user` SET `password` = CONCAT(SHA2('xxxxxxxxtest123', 256), ':xxxxxxxx:1') WHERE `username`= 'admin'

Reset From Cli

Create new user and login to admin panel and change you old user password.

<path_to_magento> php bin/magento admin:user:create --admin-user="admin" --admin-password="123123q" --admin-email="[email protected]" --admin-firstname="Admin" --admin-lastname="Admin"
Author: Qaisar Satti
Category: Magento 2
Last Modified: April 4, 2018


Magento 2 create basic module admin grid part 2

Now we move to second part how in Magento 2 create basic module admin grid. As we cover the main part of module in Magento 2 create basic module part 1. Now we focus on admin part. This tutorial cover the how to create admin controller, how to create admin menu, how to create admin custom ui component grid, how to create admin ui component form,how to create mass action and how to create custom router for admin. So start with creating the router.

Admin Router

Now we define our custom frontName for admin.Now create routes.xml in following directory

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--* Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
     -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="helloworld" frontName="helloworld">
            <module name="QaisarSatti_HelloWorld" before="Magento_Backend" />
        </route>
    </router>
</config>

Admin Menu

Now we define our menu for admin.Now create menu.xml in following directory

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--* Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
     -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
            <update id="QaisarSatti_HelloWorld::helloworld" title="Qaisar Satti" module="Magento_Backend" sortOrder="177" resource="QaisarSatti_HelloWorld::helloworld"/>
            <add id="QaisarSatti_HelloWorld::helloworldparent" title="Qaisar Satti" module="QaisarSatti_HelloWorld" sortOrder="72"  parent="QaisarSatti_HelloWorld::helloworld" resource="QaisarSatti_HelloWorld::helloworldparent" />
            <add id="QaisarSatti_HelloWorld::helloworld1" title="Manage Blog Post" module="QaisarSatti_HelloWorld" sortOrder="0" parent="QaisarSatti_HelloWorld::helloworldparent" action="helloworld/" resource="QaisarSatti_HelloWorld::helloworld1"/>
    </menu>
</config>

Admin Grid

Now we create custom grid admin.If you want to read the detail about read tutorial Magento 2 create admin controller. Grid is part of three files. Controller file, layout file, grid collection model and ui component file.

Grid Controller

i am creating the grid on my Index.php action. As follow my module create Index.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class Index extends \Magento\Backend\App\Action
{
   
    protected $resultPageFactory;

   
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context, $coreRegistry);
    }

   
    public function execute()
    {

        $resultPage = $this->resultPageFactory->create();
        $this->initPage($resultPage)->getConfig()->getTitle()->prepend(__('Manage Post'));
        return $resultPage;
    }
    protected function initPage($resultPage)
    {
         $resultPage->setActiveMenu('QaisarSatti_HelloWorld::helloworld1')
             ->addBreadcrumb(__('Qaisar Satti'), __('Qaisar Satti'))
             ->addBreadcrumb(__('Manage Post'), __('Manage Post'));

         return $resultPage;
    }

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

Grid layout

Now we create the grid layout file that connect it with ui component. Our ui component file name is helloworld_listing. So create helloworld_index_index.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\layout

<?xml version="1.0"?>
<!--
   /**
   * Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
       <referenceContainer name="content">
            <uiComponent name="helloworld_listing"/>
        </referenceContainer>
     
    </body>
</page>

Grid Collection Model

For the grid you need to create grid collection model.This collection have method that used for grid. Create Collection.php in following directory

QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid;

use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Api\Search\AggregationInterface;
use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Collection as HelloWorldCollection;

/**
 * Class Collection
 * Collection for displaying grid of sales documents
 */

class Collection extends HelloWorldCollection implements SearchResultInterface
{
    /**
     * @var AggregationInterface
     */

    protected $aggregations;

    /**
     * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory
     * @param \Psr\Log\LoggerInterface $logger
     * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy
     * @param \Magento\Framework\Event\ManagerInterface $eventManager
     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
     * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool
     * @param mixed|null $mainTable
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $eventPrefix
     * @param mixed $eventObject
     * @param mixed $resourceModel
     * @param string $model
     * @param null $connection
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb|null $resource
     *
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */

    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\EntityManager\MetadataPool $metadataPool,
        $mainTable,
        $eventPrefix,
        $eventObject,
        $resourceModel,
        $model = 'Magento\Framework\View\Element\UiComponent\DataProvider\Document',
        $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $storeManager,
            $metadataPool,
            $connection,
            $resource
        );
        $this->_eventPrefix = $eventPrefix;
        $this->_eventObject = $eventObject;
        $this->_init($model, $resourceModel);
        $this->setMainTable($mainTable);
    }

    /**
     * @return AggregationInterface
     */

    public function getAggregations()
    {
        return $this->aggregations;
    }

    /**
     * @param AggregationInterface $aggregations
     * @return $this
     */

    public function setAggregations($aggregations)
    {
        $this->aggregations = $aggregations;
    }

    /**
     * Get search criteria.
     *
     * @return \Magento\Framework\Api\SearchCriteriaInterface|null
     */

    public function getSearchCriteria()
    {
        return null;
    }

    /**
     * Set search criteria.
     *
     * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null)
    {
        return $this;
    }

    /**
     * Get total count.
     *
     * @return int
     */

    public function getTotalCount()
    {
        return $this->getSize();
    }

    /**
     * Set total count.
     *
     * @param int $totalCount
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setTotalCount($totalCount)
    {
        return $this;
    }

    /**
     * Set items list.
     *
     * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items
     * @return $this
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */

    public function setItems(array $items = null)
    {
        return $this;
    }
}

Define Data Source and Data Provider

Now we define data source for grid. Our dataSource name will be helloworld_listing_data_source and DataProvider name helloworldGridDataProvider.create di.xml in following directory

QaisarSatti\HelloWorld\etc\\

<?xml version="1.0"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
   <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
        <arguments>
            <argument name="collections" xsi:type="array">
                <item name="helloworld_listing_data_source" xsi:type="string">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
    <type name="QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">sample_posts</argument>
            <argument name="eventPrefix" xsi:type="string">helloworld_grid_collection</argument>
            <argument name="eventObject" xsi:type="string">helloworld_grid_collection</argument>
            <argument name="resourceModel" xsi:type="string">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld</argument>
        </arguments>
    </type>
    <virtualType name="helloworldGirdFilterPool" type="Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool">
        <arguments>
            <argument name="appliers" xsi:type="array">
                <item name="regular" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\RegularFilter</item>
                <item name="fulltext" xsi:type="object">Magento\Framework\View\Element\UiComponent\DataProvider\FulltextFilter</item>
            </argument>
        </arguments>
    </virtualType>
     <virtualType name="helloworldGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">helloworldGirdFilterPool</argument>
        </arguments>
    </virtualType>
   
 
</config>

Grid Action Column Url Builder

create UrlBuilder.php in following directory

QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action;

class UrlBuilder
{
    /**
     * @var \Magento\Framework\UrlInterface
     */

    protected $frontendUrlBuilder;

    /**
     * @param \Magento\Framework\UrlInterface $frontendUrlBuilder
     */

    public function __construct(\Magento\Framework\UrlInterface $frontendUrlBuilder)
    {
        $this->frontendUrlBuilder = $frontendUrlBuilder;
    }

    /**
     * Get action url
     *
     * @param string $routePath
     * @param string $scope
     * @param string $store
     * @return string
     */

    public function getUrl($routePath, $scope, $store)
    {
        $this->frontendUrlBuilder->setScope($scope);
        $href = $this->frontendUrlBuilder->getUrl(
            $routePath,
            ['_current' => false, '_query' => '___store=' . $store]
        );
        return $href;
    }
}

Grid Action Column

This will be used in action column of grid. You can add edit or any action you want to perform with current row data. create HelloWorldActions.php in following directory

QaisarSatti\HelloWorld\Ui\Component\Listing\Column\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Ui\Component\Listing\Column;

use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Ui\Component\Listing\Columns\Column;
use QaisarSatti\HelloWorld\Block\Adminhtml\HelloWorld\Grid\Renderer\Action\UrlBuilder;
use Magento\Framework\UrlInterface;

/**
 * Class PageActions
 */

class HelloWorldActions extends Column
{
    /** Url path */
    const HELLOWORLD_URL_PATH_EDIT = 'helloworld/index/edit';
    const HELLOWORLD_URL_PATH_DELETE = 'helloworld/index/delete';

    /** @var UrlBuilder */
    protected $actionUrlBuilder;

    /** @var UrlInterface */
    protected $urlBuilder;

    /**
     * @var string
     */

    private $editUrl;

    /**
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param UrlBuilder $actionUrlBuilder
     * @param UrlInterface $urlBuilder
     * @param array $components
     * @param array $data
     * @param string $editUrl
     */

    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        UrlBuilder $actionUrlBuilder,
        UrlInterface $urlBuilder,
        array $components = [],
        array $data = [],
        $editUrl = self::HELLOWORLD_URL_PATH_EDIT
    ) {
        $this->urlBuilder = $urlBuilder;
        $this->actionUrlBuilder = $actionUrlBuilder;
        $this->editUrl = $editUrl;
        parent::__construct($context, $uiComponentFactory, $components, $data);
    }

    /**
     * Prepare Data Source
     *
     * @param array $dataSource
     * @return array
     */

    public function prepareDataSource(array $dataSource)
    {
        if (isset($dataSource['data']['items'])) {
            foreach ($dataSource['data']['items'] as & $item) {
                $name = $this->getData('name');
                if (isset($item['post_id'])) {
                    $item[$name]['edit'] = [
                        'href' => $this->urlBuilder->getUrl($this->editUrl, ['id' => $item['post_id']]),
                        'label' => __('Edit')
                    ];
                    $item[$name]['delete'] = [
                        'href' => $this->urlBuilder->getUrl(self::HELLOWORLD_URL_PATH_DELETE, ['id' => $item['post_id']]),
                        'label' => __('Delete'),
                        'confirm' => [
                            'title' => __('Delete ${ $.$data.title }'),
                            'message' => __('Are you sure you wan\'t to delete a ${ $.$data.title } record?')
                        ]
                    ];
 
                }
            }

        return $dataSource;
        }
    }
}

Grid Ui Component

I already posted the detail article about Magento 2 create custom ui component admin grid. So we not going to detail explanation about it. So move on with create helloworld_listing.xml in following directory

QaisarSatti\HelloWorld\view\adminhtml\ui_component\

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
    <argument name="data" xsi:type="array">
        <item name="js_config" xsi:type="array">
            <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing_data_source</item>
            <item name="deps" xsi:type="string">helloworld_listing.helloworld_listing_data_source</item>
        </item>
        <item name="spinner" xsi:type="string">helloworld_index_columns</item>
        <item name="buttons" xsi:type="array">
            <item name="add" xsi:type="array">
                <item name="name" xsi:type="string">add</item>
                <item name="label" xsi:type="string" translate="true">Add New Blog Post</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="helloworld_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">helloworldGridDataProvider</argument>
            <argument name="name" xsi:type="string">helloworld_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">post_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                </item>
            </argument>
        </argument>
    </dataSource>
    <listingToolbar name="listing_top">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="sticky" xsi:type="boolean">true</item>
            </item>
        </argument>
        <bookmark name="bookmarks"/>
        <columnsControls name="columns_controls"/>
        <filterSearch name="fulltext"/>
        <filters name="listing_filters">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="columnsProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">storageConfig.storageConfig.listing_top.bookmarks</item>
                        <item name="namespace" xsi:type="string">current.filters</item>
                    </item>
                    <item name="templates" xsi:type="array">
                        <item name="filters" xsi:type="array">
                            <item name="select" xsi:type="array">
                                <item name="component" xsi:type="string">Magento_Ui/js/form/element/ui-select</item>
                                <item name="template" xsi:type="string">ui/grid/filters/elements/ui-select</item>
                            </item>
                        </item>
                    </item>
                    <item name="childDefaults" xsi:type="array">
                        <item name="provider" xsi:type="string">storageConfig.storageConfig.listing_top.listing_filters</item>
                        <item name="imports" xsi:type="array">
                            <item name="visible" xsi:type="string">storageConfig.storageConfig.helloworld_index_columns.${ $.index }:visible</item>
                        </item>
                    </item>
                </item>
                <item name="observers" xsi:type="array">
                    <item name="column" xsi:type="string">column</item>
                </item>
            </argument>
        </filters>
        <massaction name="listing_massaction">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
            <action name="delete">
                <argument name="data" xsi:type="array">
                    <item name="config" xsi:type="array">
                        <item name="type" xsi:type="string">delete</item>
                        <item name="label" xsi:type="string" translate="true">Delete</item>
                        <item name="url" xsi:type="url" path="helloworld/index/massDelete"/>
                        <item name="confirm" xsi:type="array">
                            <item name="title" xsi:type="string" translate="true">Delete items</item>
                            <item name="message" xsi:type="string" translate="true">Are you sure you wan't to delete selected items?</item>
                        </item>
                    </item>
                </argument>
            </action>
        </massaction>
        <paging name="listing_paging"/>
    </listingToolbar>
   
    <columns name="helloworld_index_columns">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="storageConfig" xsi:type="array">
                    <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current</item>
                </item>
                <item name="editorConfig" xsi:type="array">
                    <item name="selectProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns.ids</item>
                    <item name="enabled" xsi:type="boolean">true</item>
                    <item name="indexField" xsi:type="string">id</item>
                    <item name="clientConfig" xsi:type="array">
                        <item name="saveUrl" xsi:type="url" path="news/index/inlineEdit"/>
                        <item name="validateBeforeSave" xsi:type="boolean">false</item>
                    </item>
                </item>
                <item name="childDefaults" xsi:type="array">
                    <item name="fieldAction" xsi:type="array">
                        <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns_editor</item>
                        <item name="target" xsi:type="string">startEdit</item>
                        <item name="params" xsi:type="array">
                            <item name="0" xsi:type="string">${ $.$data.rowIndex }</item>
                            <item name="1" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="storageConfig" xsi:type="array">
                        <item name="provider" xsi:type="string">helloworld_listing.helloworld_listing.listing_top.bookmarks</item>
                        <item name="root" xsi:type="string">columns.${ $.index }</item>
                        <item name="namespace" xsi:type="string">current.${ $.storageConfig.root}</item>
                    </item>
                </item>
            </item>
        </argument>
        <selectionsColumn name="ids">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="resizeEnabled" xsi:type="boolean">false</item>
                    <item name="resizeDefaultWidth" xsi:type="string">55</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
        </selectionsColumn>
        <column name="title">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">text</item>
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">text</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Title</item>
                </item>
            </argument>
        </column>
         <column name="content">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="editor" xsi:type="array">
                        <item name="editorType" xsi:type="string">textarea</item>
                        <item name="validation" xsi:type="array">
                            <item name="required-entry" xsi:type="boolean">true</item>
                        </item>
                    </item>
                    <item name="label" xsi:type="string" translate="true">Content</item>
                </item>
            </argument>
        </column>  
        <actionsColumn name="actions" class="QaisarSatti\HelloWorld\Ui\Component\Listing\Column\HelloWorldActions">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="resizeEnabled" xsi:type="boolean">false</item>
                    <item name="resizeDefaultWidth" xsi:type="string">107</item>
                    <item name="indexField" xsi:type="string">post_id</item>
                </item>
            </argument>
        </actionsColumn>
    </columns>
    <container name="sticky">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/sticky/sticky</item>
                <item name="toolbarProvider" xsi:type="string">helloworld_listing.helloworld_listing.listing_top</item>
                <item name="listingProvider" xsi:type="string">helloworld_listing.helloworld_listing.helloworld_index_columns</item>
            </item>
        </argument>
    </container>
</listing>

Grid Mass Action

Now we create the mass action controller for grid. You can any mass action like enabled, disabled and any other mass action. Now i am creating mass delete action. Create controller for MassDelete.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index\

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

use Magento\Framework\Controller\ResultFactory;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld\CollectionFactory;

class MassDelete extends \Magento\Backend\App\Action
{
    /**
     * @var Filter
     */

    protected $filter;

    /**
     * @var CollectionFactory
     */

    protected $collectionFactory;

    /**
     * @param Context $context
     * @param Filter $filter
     * @param CollectionFactory $collectionFactory
     */

    public function __construct(Context $context, Filter $filter, CollectionFactory $collectionFactory)
    {
        $this->filter = $filter;
        $this->collectionFactory = $collectionFactory;
        parent::__construct($context);
    }

    /**
     * Execute action
     *
     * @return \Magento\Backend\Model\View\Result\Redirect
     * @throws \Magento\Framework\Exception\LocalizedException|\Exception
     */

    public function execute()
    {
        $collection = $this->filter->getCollection($this->collectionFactory->create());
        $collectionSize = $collection->getSize();

        foreach ($collection as $page) {
            $page->delete();
        }

        $this->messageManager->addSuccess(__('A total of %1 record(s) have been deleted.', $collectionSize));

        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }
}

Now we complete the custom admin grid. Now move to third part Magento 2 create basic module admin from part 3.

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 9, 2018


Magento 2 create basic module part 1

Today we discuss how in magento 2 create basic module. This tutorial include the complete module sections frontend, admin end, custom model, custom admin grid, custom admin form, frontend controller, admin controller and admin menu. I already posted a tutorial about create a hello world module. Now we will go one step further and create a complete basic module. So let start with our example. My module name is hello world.

Module registration

First you register your module or extension. Create registration.php in following directory

QaisarSatti/HelloWorld/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */


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

Module declaration

First you declare your module or extension. In module.xml you declare your schema_version and setup_version of module that are stored in setup_module table . Now Create module.xml in following directory

QaisarSatti/HelloWorld/etc/

<?xml version="1.0"?>
<!--
/**
* Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
*/

-->    
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
   <module name="QaisarSatti_HelloWorld" schema_version="0.0.1" setup_version="0.0.1"/>
</config>

Module Setup

Now we create custom table sample_posts for module. You can read further on tutorial Magento 2 Create a install Schema. Now we Create InstallSchema.php in following directory

QaisarSatti/HelloWorld/Setup/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;

class InstallSchema implements InstallSchemaInterface {

    public function install( SchemaSetupInterface $setup, ModuleContextInterface $context ) {
        $installer = $setup;

        $installer->startSetup();

        $table = $installer->getConnection()->newTable(
            $installer->getTable( 'sample_posts' )
        )->addColumn(
            'post_id',
            Table::TYPE_SMALLINT,
            null,
            [ 'identity' => true, 'nullable' => false, 'primary' => true ],
            'Post ID'
        )->addColumn(
            'title',
            Table::TYPE_TEXT,
            255,
            [ 'nullable' => false ],
            'Post Title'
        )->addColumn(
            'content',
            Table::TYPE_TEXT,
            '2M',
            [ ],
            'Post Content'
        )->setComment(
            'Sample Post Table'
        );

        $installer->getConnection()->createTable( $table );

        $installer->endSetup();
    }
}

Module Model

I already discuss model in Magento 2 create custom model tutorial. So we go to directly creating models file.

Model File

Create HelloWorld.php in following directory

QaisarSatti/HelloWorld/Model/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */


namespace QaisarSatti\HelloWorld\Model;



    class HelloWorld extends \Magento\Framework\Model\AbstractModel  
    {  
        protected function _construct()
        {
            $this->_init('QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld');
        }
}

ResouceModel File

Create HelloWorld.php in following directory

QaisarSatti/HelloWorld/Model/ResouceModel/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */



namespace QaisarSatti\HelloWorld\Model\ResourceModel;


use \Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class HelloWorld extends AbstractDb

{
    protected function _construct()

    {
        $this->_init('sample_posts', 'post_id');

    }
   

}

AbstractCollection Model File

Create AbstractCollection.php in following directory

QaisarSatti/HelloWorld/Model/ResouceModel/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */

namespace QaisarSatti\HelloWorld\Model\ResourceModel;

use Magento\Store\Model\Store;

/**
 * Abstract collection of CMS pages and blocks
 */

abstract class AbstractCollection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */

    protected $storeManager;

    /**
     * @var \Magento\Framework\EntityManager\MetadataPool
     */

    protected $metadataPool;

   
    public function __construct(
        \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory,
        \Psr\Log\LoggerInterface $logger,
        \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy,
        \Magento\Framework\Event\ManagerInterface $eventManager,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\EntityManager\MetadataPool $metadataPool,
        \Magento\Framework\DB\Adapter\AdapterInterface $connection = null,
        \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null
    ) {
        $this->storeManager = $storeManager;
        $this->metadataPool = $metadataPool;
        parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource);
    }

    /**
     * Perform operations after collection load
     *
     * @param string $tableName
     * @param string|null $linkField
     * @return void
     */

    protected function performAfterLoad($tableName, $linkField)
    {
        $linkedIds = $this->getColumnValues($linkField);
       
       
    }

    /**
     * Add field filter to collection
     *
     * @param array|string $field
     * @param string|int|array|null $condition
     * @return $this
     */

    public function addFieldToFilter($field, $condition = null)
    {
       

        return parent::addFieldToFilter($field, $condition);
    }

    /**
     * Add filter by store
     *
     * @param int|array|Store $store
     * @param bool $withAdmin
     * @return $this
     */

    abstract public function addStoreFilter($store, $withAdmin = true);

    /**
     * Perform adding filter by store
     *
     * @param int|array|Store $store
     * @param bool $withAdmin
     * @return void
     */

    protected function performAddStoreFilter($store, $withAdmin = true)
    {
        if ($store instanceof Store) {
            $store = [$store->getId()];
        }

        if (!is_array($store)) {
            $store = [$store];
        }

        if ($withAdmin) {
            $store[] = Store::DEFAULT_STORE_ID;
        }

        $this->addFilter('store', ['in' => $store], 'public');
    }

    /**
     * Join store relation table if there is store filter
     *
     * @param string $tableName
     * @param string|null $linkField
     * @return void
     */

    protected function joinStoreRelationTable($tableName, $linkField)
    {
        if ($this->getFilter('store')) {
            $this->getSelect()->join(
                ['store_table' => $this->getTable($tableName)],
                'main_table.' . $linkField . ' = store_table.' . $linkField,
                []
            )->group(
                'main_table.' . $linkField
            );
        }
        parent::_renderFiltersBefore();
    }

    /**
     * Get SQL for get record count
     *
     * Extra GROUP BY strip added.
     *
     * @return \Magento\Framework\DB\Select
     */

    public function getSelectCountSql()
    {
        $countSelect = parent::getSelectCountSql();
        $countSelect->reset(\Magento\Framework\DB\Select::GROUP);

        return $countSelect;
    }
}

Collection Model File

Create Collection.php in following directory

QaisarSatti/HelloWorld/Model/ResouceModel/HelloWorld/

<?php
/**
 * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
 */



namespace QaisarSatti\HelloWorld\Model\ResourceModel\HelloWorld;


use QaisarSatti\HelloWorld\Model\ResourceModel\AbstractCollection;

class Collection extends AbstractCollection
{
    /**
     * @var string
     */

    protected $_idFieldName = 'post_id';

    /**
     * Load data for preview flag
     *
     * @var bool
     */

    protected $_previewFlag;

    /**
     * Define resource model
     *
     * @return void
     */

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

   
    public function setFirstStoreFlag($flag = false)
    {
        $this->_previewFlag = $flag;
        return $this;
    }

    /**
     * Add filter by store
     *
     * @param int|array|\Magento\Store\Model\Store $store
     * @param bool $withAdmin
     * @return $this
     */

    public function addStoreFilter($store, $withAdmin = true)
    {
       
        return $this;
    }

    /**
     * Perform operations after collection load
     *
     * @return $this
     */

    protected function _afterLoad()
    {
       
        return parent::_afterLoad();
    }

    /**
     * Perform operations before rendering filters
     *
     * @return void
     */

    protected function _renderFiltersBefore()
    {
        return parent::_renderFiltersBefore();
    }
}

Now the part 1 is complete now we got part 2 Magento 2 create basic module admin.

Author: Qaisar Satti
Category: Magento 2
Last Modified: April 6, 2018


Magento 2 create admin controller

Today we discuss how in magento 2 create admin controller. This tutorial include the basic structure of admin controller and how to execute admin controller. Now we start with our example.

For the custom admin controller first create the routes.xml file in following directory.

QaisarSatti/HelloWorld/etc/adminhtml/

<?xml version="1.0"?>
<!--/**
   * Hello World
   *
   * @category    QaisarSatti
   * @package     QaisarSatti_HelloWorld
   * @author      Muhammad Qaisar Satti
   * @Email       [email protected]
   *
   */ -->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="helloworld" frontName="helloworld">
            <module name="QaisarSatti_HelloWorld" before="Magento_Backend" />
        </route>
    </router>
</config>

Now create the admin controller. Index.php in following directory

QaisarSatti\HelloWorld\Controller\Adminhtml\Index

<?php
/**
    * Hello World
    *
    * @category    QaisarSatti
    * @package     QaisarSatti_HelloWorld
    * @author      Muhammad Qaisar Satti
    * @Email       [email protected]
    *
    */

namespace QaisarSatti\HelloWorld\Controller\Adminhtml\Index;

class Index extends \Magento\Backend\App\Action
{
   
    protected $resultPageFactory;

   
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory
    ) {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context, $coreRegistry);
    }

   
    public function execute()
    {

        echo "My admin controller"; exit;
       

    }
   

 
    protected function _isAllowed()
    {
        return true;
    }
}

Note: This is basic example how to create custom admin controller

Author: Qaisar Satti
Category: Magento 2
Last Modified: February 8, 2018