Magento 2 modul fejlesztés lépésről lépésre – 2. rész

Ebben a cikkben a következő témákat öleljük fel:

1) Admin menüpont és táblázat (grid) elkészítése

Első lépésben létrehozunk az adminisztrációs felületen a modulunkhoz tartozó menüpontot. Ezt külön (új) főmenüben is elhelyezhetjük, de célszerű a modul működéséhez igazodva besorolni a már létező főmenüpontok alá. Jelen esetben a Content főmenüpontban helyezzük el a sajátunkat. Ehhez szükségünk lesz egy új file-ra. A menüpontot az app/code/Aion/Test/etc/adminhtml/ könyvtárban lévő menu.xml-ben valósítjuk meg. A fájl tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Aion_Test::content_elements" title="Test Extension" module="Magento_Backend" sortOrder="10" parent="Magento_Backend::content"
             resource="Magento_Backend::content_elements"/>
        <add id="Aion_Test::aion_test" title="Manage Items" module="Aion_Test" sortOrder="10" parent="Aion_Test::content_elements" action="test/test"
             resource="Aion_Test::test"/>
    </menu>
</config>

A file-ban első lépésben definiálunk egy főelemet, ami nem más, mint az id=Aion_Test::content_elements és a menüpontot ez alá helyezzük el, úgy hogy a menüpont (id=Aion_Test::aion_test) parent-nél a főelemet adjuk meg. Ha mindent jól csináltunk, az adminisztrációs felületen a Content főmenüpontban megjelenik a saját almenüpontunk is. A menüpontnál még fontos megemlíteni az Action=”test/test” paramétert, ami a később kialakítandó adminhtml controller útvonalát hivatott megadni.   A következő lépésben szükséges elkészíteni az adminhtml controllert és layout file-t, ami a grid megjelenítésért felelős. Azonban előtte csinálunk egy abstract controller osztályt, hogy a backend jogosultság kezelést egy helyen valósítsuk meg.   Az abstract controller osztályt az app/code/Aion/Test/Controller/Adminhtml/ könyvtárban lévő Test.php-ban valósítjuk meg. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml;

/**
 * Aion manage items controller
 */
abstract class Test extends \Magento\Backend\App\Action
{
    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     */
    public function __construct(\Magento\Backend\App\Action\Context $context, \Magento\Framework\Registry $coreRegistry)
    {
        $this->_coreRegistry = $coreRegistry;
        parent::__construct($context);
    }

    /**
     * Init page
     *
     * @param \Magento\Backend\Model\View\Result\Page $resultPage
     * @return \Magento\Backend\Model\View\Result\Page
     */
    protected function initPage($resultPage)
    {
        $resultPage->setActiveMenu('Aion_Test::aion_test')
            ->addBreadcrumb(__('Test'), __('Test'))
            ->addBreadcrumb(__('Items'), __(''));
        return $resultPage;
    }

    /**
     * Check the permission to run it
     *
     * @return boolean
     */
    protected function _isAllowed()
    {
        return $this->_authorization->isAllowed('Aion_Test::test_menu');
    }
}

Az abstract controller initPage() függvénye (metódusa) felelős az aktív menüpont beállítása mellett a breadcrumb (morzsa menü) útvonal beállításáért is. A másik fontos függvény az _isAllowed(), ami az adminisztrátor jogosultságot ellenőrzi és kezeli.   Ezután elkészítjük az admin táblázat (grid) kezeléséhez szükséges controllert is, amit az imént említett abstract controller-ből fogunk kiterjeszteni. A controller osztályt az app/code/Aion/Test/Controller/Adminhtml/Test könyvtárban lévő Index.php-ban valósítjuk meg. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

class Index extends \Aion\Test\Controller\Adminhtml\Test
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\Framework\View\Result\PageFactory $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);
    }

    /**
     * Index action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $this->initPage($resultPage)->getConfig()->getTitle()->prepend(__('Items'));
        return $resultPage;
    }
}

Az Index controller felelős az admin táblázat (grid) megjelenítésért. A Magento 2.0-ban minden controller osztály (file) valójában egy action-nek felel meg. Vagyis jelen esetben a Magento 1.x-ből megismert IndexAction() függvényt immár az execute() függvény helyettesíti. Tehát minden controller action-höz külön controller file tartozik és egyetlen execute() függvény. Ez első látásra felvetheti a kérdést, hogy miért jó ez? Lényegében így a teljes modul kódja jobban átlátható, mint a korábban Magento 1.x-ben lévő controller-ek esetében, amelyek sok esetben a fejlesztés végére hosszú script-et eredményeztek. A controller-ben lévő $resultPage és $this->resultPageFactory helyettesíti Magento 1.x-ből megismert $this->loadLayout() és $this->renderLayout() hívásokat.   Ahhoz, hogy a Magento 2.0 felismerje a létrehozott adminhtml controller-ek útvonalát, ezt definiálnunk kell egy külön fájl-ban. Az útvonal definiálását az app/code/Aion/Test/etc/adminhtml/ könyvtárban lévő routes.xml-ban valósítjuk meg. A fájl tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="test" frontName="test">
            <module name="Aion_Test" before="Magento_Backend" />
        </route>
    </router>
</config>

A fájlban két lényeges tag és hozzá tartozó paraméter látható. Az első a <router id=”admin”> ami jelzi, hogy ez egy backend útvonal. A második a <route id=”test” frontName=”test”> ahol a frontName határozza meg az elkészült adminhtml controllerek fő útvonalát (az admin url utáni első paramétert). Következő lépésben létre kell hozni a collection-t, ami a fenti admin táblázatot (grid) fogja kiszolgálni adatokkal. A collection-t az app/code/Aion/Model/ResourceModel/Test/Grid/ könyvtárban lévő Collection.php-ban valósítjuk meg. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Model\ResourceModel\Test\Grid;

use Magento\Framework\Api\Search\SearchResultInterface;
use Magento\Framework\Search\AggregationInterface;
use Aion\Test\Model\ResourceModel\Test\Collection as TestCollection;

/**
 * Collection for displaying grid of Aion Items
 */
class Collection extends TestCollection 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 string $mainTable
     * @param string $eventPrefix
     * @param string $eventObject
     * @param string $resourceModel
     * @param string $model
     * @param string|null $connection
     * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $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,
        $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,
            $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;
    }


    /**
     * Retrieve all ids for collection
     * Backward compatibility with EAV collection
     *
     * @param int $limit
     * @param int $offset
     * @return array
     */
    public function getAllIds($limit = null, $offset = null)
    {
        return $this->getConnection()->fetchCol($this->_getAllIdsSelect($limit, $offset), $this->_bindParams);
    }

    /**
     * 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;
    }
}

A fájlban definiált osztály felelős a kialakítandó admin táblázatban(grid) az adatok hozzáadásáért, keresés és lapozás implementálásáért. A következőkben leírt UI Components megfelelő működéséhez szükséges a fenti függvények implementálása. Másik előnye, hogy az itt definiált osztályt könnyen máshol is fel tudjuk használni, amennyiben máshol is megszeretnénk jeleníteni a modul adatait admin táblázatban(grid), például egy product vagy customer ajax tab-on az adminisztrációs felületen.   Már csak egy dolog van hátra, ami nem más, mint az Index controllerhez tartozó layout file elkészítése. A layout file-t az app/code/Aion/Test/view/adminhtml/layout/ könyvtárban lévő test_test_index.xml-ban valósítjuk meg. Jól látható a korábban definiált route a fájl nevében: alap route -> könyvtár -> controller action. A fájl tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="test_test_listing"/>
        </referenceContainer>
    </body>
</page>

A layout fájlban lévő „content” referencia konténerben van definiálva a korábban említett UI component file neve, amire a következő pontban térünk ki részletesen.

2) UI Components avagy az admin táblázat (grid) új kialakítása

A Magento 2.0-ban bevezetett UI component-ek használatával sokkal könnyebben tudunk admin táblázatot (grid) létrehozni és emellett az adminisztrátor számára sokkal több lehetőséget nyújt a táblázatban történő kereséshez, szűréshez, az oszlopok tetszőleges megjelenítéséhez. Emellett külön megjelenítések menthetők le.   A UI component-ek működéséhez több fájlt is létre kell hoznunk és megfelelően implementálnunk. A legfontosabb fájl, ami az admin táblázat működését és megjelenését meghatározza egy xml fájl. Ez a mi modulunk esetében a test_test_listing.xml nevet kapta (lásd előző pont) és az app/code/Aion/Test/view/adminhtml/ui_component könyvtárban van elhelyezve. A fájl nagyon hosszú, így tartalmát darabolva jelenítjük meg cikkünkben.

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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">test_test_listing.test_test_listing_data_source</item>
            <item name="deps" xsi:type="string">test_test_listing.test_test_listing_data_source</item>
        </item>
        <item name="spinner" xsi:type="string">test_test_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 Item</item>
                <item name="class" xsi:type="string">primary</item>
                <item name="url" xsi:type="string">*/*/new</item>
            </item>
        </item>
    </argument>
    <dataSource name="test_test_listing_data_source">
        <argument name="dataProvider" xsi:type="configurableObject">
            <argument name="class" xsi:type="string">TestGridDataProvider</argument>
            <argument name="name" xsi:type="string">test_test_listing_data_source</argument>
            <argument name="primaryFieldName" xsi:type="string">test_id</argument>
            <argument name="requestFieldName" xsi:type="string">id</argument>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="update_url" xsi:type="url" path="mui/index/render"/>
                </item>
            </argument>
        </argument>
        <argument name="data" xsi:type="array">
            <item name="js_config" xsi:type="array">
                <item name="component" xsi:type="string">Magento_Ui/js/grid/provider</item>
            </item>
        </argument>
    </dataSource>
…

A fájlban lévő első argument tag-ben vannak definiálva az alábbiak:

  • adat forrás név (test_test_listing_data_source) lásd második dataSource tag: <dataSource name=”test_test_listing_data_source”>
  • oszlopok tag neve: test_test_columns, erre továbbiakban lesz szükségünk
  • az új elem hozzáadása és egyéb gombok definiálása, lásd: <item name=”buttons” xsi:type=”array”> tag
…
<container name="listing_top">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="template" xsi:type="string">ui/grid/toolbar</item>
        </item>
    </argument>
    <bookmark name="bookmarks">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="storageConfig" xsi:type="array">
                    <item name="namespace" xsi:type="string">test_test_listing</item>
                </item>
            </item>
        </argument>
    </bookmark>
    <component name="columns_controls">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="columnsData" xsi:type="array">
                    <item name="provider" xsi:type="string">test_test_listing.test_test_listing.test_test_columns</item>
                </item>
                <item name="component" xsi:type="string">Magento_Ui/js/grid/controls/columns</item>
                <item name="displayArea" xsi:type="string">dataGridActions</item>
            </item>
        </argument>
    </component>
…

Az xml fájlt tovább böngészve definiálásra kerülnek a táblázat felett elhelyezkedő funkciók. Ezek az alábbiak:

  • lementhetjük az aktuális táblázat megjelenést több view-ban, lásd: <bookmark name=”bookmarks”> tag
  • beállíthatjuk túl sok oszlop esetén, hogy melyek jelenjenek meg és az előbb említett bookmarks-nál menthetjük le, lásd: <component name=”columns_controls”> tag
…
<filterSearch name="fulltext">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="provider" xsi:type="string">test_test_listing.test_test_listing_data_source</item>
            <item name="chipsProvider" xsi:type="string">test_test_listing.test_test_listing.listing_top.listing_filters_chips</item>
            <item name="storageConfig" xsi:type="array">
                <item name="provider" xsi:type="string">test_test_listing.test_test_listing.listing_top.bookmarks</item>
                <item name="namespace" xsi:type="string">current.search</item>
            </item>
        </item>
    </argument>
</filterSearch>
<filters name="listing_filters">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="columnsProvider" xsi:type="string">test_test_listing.test_test_listing.test_test_columns</item>
            <item name="storageConfig" xsi:type="array">
                <item name="provider" xsi:type="string">test_test_listing.test_test_listing.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">test_test_listing.test_test_listing.listing_top.listing_filters</item>
                <item name="imports" xsi:type="array">
                    <item name="visible" xsi:type="string">test_test_listing.test_test_listing.test_test_columns.${ $.index }:visible</item>
                </item>
            </item>
        </item>
    </argument>
</filters>
…

Hozzáadásra kerül a text alapú kereső és a táblázat szűrése (filters). Ezek az alábbiak:

  • varchar, text típusú oszlopokban kereshetünk egy input mezőben, lásd: <filterSearch name=”fulltext”> tag
  • minden egyes oszlopot szűrhetünk megfelelő paraméterek szerint view(Aion\Test\Ui\Component\Listing\Column\Test\Options), select, dátum, ID(range), text típusú szűrések, lásd: <filters name=”listing_filters”> tag
…
<massaction name="listing_massaction">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="selectProvider" xsi:type="string">test_test_listing.test_test_listing.test_test_columns.ids</item>
            <item name="indexField" xsi:type="string">test_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="test/test/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>
    <action name="disable">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="type" xsi:type="string">disable</item>
                <item name="label" xsi:type="string" translate="true">Disable</item>
                <item name="url" xsi:type="url" path="test/test/massDisable"/>
            </item>
        </argument>
    </action>
    <action name="enable">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="type" xsi:type="string">enable</item>
                <item name="label" xsi:type="string" translate="true">Enable</item>
                <item name="url" xsi:type="url" path="test/test/massEnable"/>
            </item>
        </argument>
    </action>
</massaction>
…

A massaction tag-en belül kerülnek hozzáadásra tetszőleges általunk definiált műveletek, melyek a tömeges adatmódosításra szolgálnak. A modulunkban ezek az alábbiak:

  • tömeges törlés, lásd: <action name=”delete”> tag
  • tömeges engedélyezés és tiltás, lásd: <action name=”disable”> és <action name=”enable”> tag-ek. Ezek a modulunk adatbázis táblájában korában kialakított is_active adatot módosítják.
…    
    <paging name="listing_paging">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="storageConfig" xsi:type="array">
                    <item name="provider" xsi:type="string">test_test_listing.test_test_listing.listing_top.bookmarks</item>
                    <item name="namespace" xsi:type="string">current.paging</item>
                </item>
                <item name="selectProvider" xsi:type="string">test_test_listing.test_test_listing.test_test_columns.ids</item>
            </item>
        </argument>
    </paging>
</container>
…

A <paging name=”listing_paging”> tag implementálja lapozást és a listázott elemek számának választhatóságát (select) a táblázatunkban.

…
<columns name="test_test_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">test_test_listing.test_test_listing.listing_top.bookmarks</item>
                <item name="namespace" xsi:type="string">current</item>
            </item>
        </item>
            <item name="childDefaults" xsi:type="array">
                <item name="fieldAction" xsi:type="array">
                    <item name="provider" xsi:type="string">test_test_listing.test_test_listing.test_test_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">test_test_listing.test_test_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="indexField" xsi:type="string">test_id</item>
            </item>
        </argument>
    </selectionsColumn>
…

Fentiek után következik a táblázat oszlopainak meghatározása, lásd: <columns name=”test_test_columns”> tag. Ennek nevét már a fájl elején definiáltuk. A korábban említett mass action-ökhez beállított ID mező, lásd: <selectionsColumn name=”ids”> tag.

…   
        <column name="test_id">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">textRange</item>
                    <item name="sorting" xsi:type="string">asc</item>
                    <item name="label" xsi:type="string" translate="true">ID</item>
                </item>
            </argument>
        </column>
        <column name="name">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <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="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Name</item>
                </item>
            </argument>
        </column>
        <column name="email">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <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="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Email</item>
                </item>
            </argument>
        </column>
        <column name="creation_time" class="Magento\Ui\Component\Listing\Columns\Date">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">dateRange</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
                    <item name="dataType" xsi:type="string">date</item>
                    <item name="label" xsi:type="string" translate="true">Created</item>
                </item>
            </argument>
        </column>
        <column name="update_time" class="Magento\Ui\Component\Listing\Columns\Date">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">dateRange</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item>
                    <item name="dataType" xsi:type="string">date</item>
                    <item name="label" xsi:type="string" translate="true">Modified</item>
                </item>
            </argument>
        </column>
        <column name="sort_order">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <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="filter" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Sort Order</item>
                </item>
            </argument>
        </column>
        <column name="is_active">
            <argument name="data" xsi:type="array">
                <item name="options" xsi:type="array">
                    <item name="disable" xsi:type="array">
                        <item name="value" xsi:type="string">0</item>
                        <item name="label" xsi:type="string" translate="true">Disabled</item>
                    </item>
                    <item name="enable" xsi:type="array">
                        <item name="value" xsi:type="string">1</item>
                        <item name="label" xsi:type="string" translate="true">Enabled</item>
                    </item>
                </item>
                <item name="config" xsi:type="array">
                    <item name="filter" xsi:type="string">select</item>
                    <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/select</item>
                    <item name="editor" xsi:type="string">select</item>
                    <item name="dataType" xsi:type="string">select</item>
                    <item name="label" xsi:type="string" translate="true">Status</item>
                </item>
            </argument>
        </column>
        <actionsColumn name="actions" class="Aion\Test\Ui\Component\Listing\Column\TestActions">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="indexField" xsi:type="string">test_id</item>
                </item>
            </argument>
        </actionsColumn>
    </columns>
</listing>

Ezt követően a táblázatban lévő oszlopokat kell meghatároznunk. Az egyes oszlopoknál beállíthatjuk a típust, pl.: text, select, textRange, dateRange stb. Az utolsó oszlop az alap action-öket tartalmazza, lásd: <actionsColumn name=”actions” class=”Aion\Test\Ui\Component\Listing\Column\TestActions”> tag   Ezzel el is készültünk a grid definíciós xml-lel (test_test_listing.xml). A továbbiakban megnézünk néhány osztályt, ami az utolsó oszlopban lévő action-ökért felel.

3) UI component osztályok

Az előző pontban kialakított grid definíciós xml-ben található action oszlop működéséhez szükségünk van egy osztályra, mely a megjelenítést és a működést segítik.   Az első az előző pontban látható <actionsColumn name=”actions” class=”Aion\Test\Ui\Component\Listing\Column\TestActions”> tag-ben látható a TestActions osztály. A fájl az app/code/Aion/Test/Ui/Component/Listing/Column könyvtárban van elhelyezve TestActions.php néven. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Ui\Component\Listing\Column;

use Magento\Framework\UrlInterface;
use Magento\Framework\View\Element\UiComponent\ContextInterface;
use Magento\Framework\View\Element\UiComponentFactory;
use Magento\Ui\Component\Listing\Columns\Column;

/**
 * Class TestActions
 */
class TestActions extends Column
{
    /**
     * Url path
     */
    const URL_PATH_EDIT = 'test/test/edit';
    const URL_PATH_DELETE = 'test/test/delete';

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

    /**
     * Constructor
     *
     * @param ContextInterface $context
     * @param UiComponentFactory $uiComponentFactory
     * @param UrlInterface $urlBuilder
     * @param array $components
     * @param array $data
     */
    public function __construct(
        ContextInterface $context,
        UiComponentFactory $uiComponentFactory,
        UrlInterface $urlBuilder,
        array $components = [],
        array $data = []
    ) {
        $this->urlBuilder = $urlBuilder;
        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) {
                if (isset($item['test_id'])) {
                    $item[$this->getData('name')] = [
                        'edit' => [
                            'href' => $this->urlBuilder->getUrl(
                                static::URL_PATH_EDIT,
                                [
                                    'test_id' => $item['test_id']
                                ]
                            ),
                            'label' => __('Edit')
                        ],
                        'delete' => [
                            'href' => $this->urlBuilder->getUrl(
                                static::URL_PATH_DELETE,
                                [
                                    'test_id' => $item['test_id']
                                ]
                            ),
                            'label' => __('Delete'),
                            'confirm' => [
                                'title' => __('Delete "${ $.$data.name }"'),
                                'message' => __('Are you sure you wan\'t to delete a "${ $.$data.name }" record?')
                            ]
                        ]
                    ];
                }
            }
        }

        return $dataSource;
    }
}

Az osztály előállítja a mass action megjelenítéséhez szükséges tömböt a megfelelő formátumban. A file elején lévő konstantsoknál fontos a pontos útvonal meghatározása, hogy a megfelelő adminhtml controller-re mutassanak.

4) Adminhtml controller-ek

A grid teljes működéséhez néhány controller-t még el kell készíteni. Nézzük sorban őket. A tömeges törléshez a massDelete controller-t használjuk. A fájl az app/code/Aion/Test/Controller/Adminhtml/Test/ könyvtárban van elhelyezve MassDelete.php néven. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

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

/**
 * Class MassDelete
 */
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 $item) {
            $item->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('*/*/');
    }
}

A controller osztály execute() függvénye – vagyis az action – egy collection-t kap (\Magento\Ui\Component\MassAction\Filter osztálytól), amin végig iterálva törli az elemeket. A tömeges státusz módosításhoz a massEnable és massDisable controller-eket használjuk. A fájlok az app/code/Aion/Test/Controller/Adminhtml/Test/ könyvtárban vannak elhelyezve MassEnable.php és MassDisable.php néven. A fájlok tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

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

/**
 * Class MassEnable
 */
class MassEnable 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());

        foreach ($collection as $item) {
            $item->setIsActive(true);
            $item->save();
        }

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

        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
        return $resultRedirect->setPath('*/*/');
    }
}
<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

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

/**
 * Class MassDisable
 */
class MassDisable 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());

        foreach ($collection as $item) {
            $item->setIsActive(false);
            $item->save();
        }

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

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

A két controller működése nagyon hasonló. Mindkettő a Filter osztálytól kapott collection-ön iterál végig, és állítja be az is_active data kulcsot massEnbale esetén true-ra, míg massDisable esetén false-ra, majd menti a collection elemeit.

5) Object manager konfigurációs

Ahhoz, hogy az elkészített admin táblázat(grid) megfelelően működjön, meg kell adnunk a forrás adat objektumokat és filter-eket. Ehhez szükségünk lesz egy definíciós xml-re. A fájl az app/code/Aion/Test/etc/ könyvtárban van elhelyezve di.xml néven. A fájl tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<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="test_test_listing_data_source" xsi:type="string">Aion\Test\Model\ResourceModel\Test\Grid\Collection</item>
            </argument>
        </arguments>
    </type>
    <type name="Aion\Test\Model\ResourceModel\Test\Grid\Collection">
        <arguments>
            <argument name="mainTable" xsi:type="string">aion_test</argument>
            <argument name="eventPrefix" xsi:type="string">aion_test_grid_collection</argument>
            <argument name="eventObject" xsi:type="string">test_grid_collection</argument>
            <argument name="resourceModel" xsi:type="string">Aion\Test\Model\ResourceModel\Test</argument>
        </arguments>
    </type>
    <virtualType name="TestGirdFilterPool" 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="TestGridDataProvider" type="Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider">
        <arguments>
            <argument name="collection" xsi:type="object" shared="false">Aion\Test\Model\ResourceModel\Test\Collection</argument>
            <argument name="filterPool" xsi:type="object" shared="false">TestGirdFilterPool</argument>
        </arguments>
    </virtualType>
</config>

Ebben a fájlban definiáljuk a grid-hez szükséges collection-t (lásd: <item name=”test_test_listing_data_source” xsi:type=”string”>Aion\Test\Model\ResourceModel\Test\Grid\Collection</item>), filter-t és data provider-t, mely UI component megfelelő működéséhez szükséges.   Az egyes elemek editálását, mentését és egyenkénti törlését a következőkben írjuk le.

6) Editáláshoz szükséges admin block-ok létrehozása

Ahhoz, hogy a modulhoz tartozó adatokat létre tudjuk hozni az admin felületen és szerkeszteni tudjuk, szükségünk lesz a megfelelő osztályokra. Első lépésben a container osztályt kell létrehozni, mely később a form-ot fogja tartalmazni. Az osztályt az Aion/Test/Block/Adminhtml/ könyvtárban lévő Test.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Block\Adminhtml;

/**
 * Adminhtml Aion items content block
 */
class Test extends \Magento\Backend\Block\Widget\Grid\Container
{
    /**
     * @return void
     */
    protected function _construct()
    {
        $this->_blockGroup = 'Aion_Test';
        $this->_controller = 'adminhtml_test';
        $this->_headerText = __('Items');
        $this->_addButtonLabel = __('Add New Item');
        parent::_construct();
    }
}

Az osztályban lényeges a megfelelő blockGroup és controller meghatározása.   A következő lépésben szükségünk lesz a form container osztályra. Itt határozzuk meg szerkesztetés alatt álló objektum admin oldalának title-jét, és adhatunk hozzá tetszőleges button-okat az alap gombokon kívül, vagy távolíthatunk el. Az osztályt az Aion/Test/Block/Adminhtml/Test könyvtárban lévő Edit.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Block\Adminhtml\Test;

/**
 * Aion item edit form container
 */
class Edit extends \Magento\Backend\Block\Widget\Form\Container
{
    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;

    /**
     * @param \Magento\Backend\Block\Widget\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Widget\Context $context,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        $this->_coreRegistry = $registry;
        parent::__construct($context, $data);
    }

    /**
     * @return void
     */
    protected function _construct()
    {
        $this->_objectId = 'test_id';
        $this->_blockGroup = 'Aion_Test';
        $this->_controller = 'adminhtml_test';

        parent::_construct();

        $this->buttonList->update('save', 'label', __('Save Item'));
        $this->buttonList->update('delete', 'label', __('Delete Item'));

        $this->buttonList->add(
            'saveandcontinue',
            [
                'label' => __('Save and Continue Edit'),
                'class' => 'save',
                'data_attribute' => [
                    'mage-init' => ['button' => ['event' => 'saveAndContinueEdit', 'target' => '#edit_form']],
                ]
            ],
            -100
        );

    }

    /**
     * Get edit form container header text
     *
     * @return \Magento\Framework\Phrase
     */
    public function getHeaderText()
    {
        if ($this->_coreRegistry->registry('test_item')->getId()) {
            return __("Edit Block '%1'", $this->escapeHtml($this->_coreRegistry->registry('test_item')->getName()));
        } else {
            return __('New Item');
        }
    }
}

Amennyiben WYSWYG editort is szeretnénk használni például textarea típusú mezőhöz, akkor azt a _construct() függvényben kell elhelyezni, vagy a prepareLayout() függvényben. Az osztályban lévő getHeaderText() függvény határozza meg az admin oldal title értékét.   Az utolsó block, amit el kell készítenünk, a form megjelenítését és kezelését végzi. Az osztályt az Aion/Test/Block/Adminhtml/Test/Edit könyvtárban lévő Form.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Block\Adminhtml\Test\Edit;

/**
 * Adminhtml Aion item edit form
 */
class Form extends \Magento\Backend\Block\Widget\Form\Generic
{
    /**
     * @var \Magento\Cms\Model\Wysiwyg\Config
     */
    protected $_wysiwygConfig;

    /**
     * @var \Magento\Store\Model\System\Store
     */
    protected $_systemStore;

    /**
     * @param \Magento\Backend\Block\Template\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig
     * @param \Magento\Store\Model\System\Store $systemStore
     * @param array $data
     */
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Cms\Model\Wysiwyg\Config $wysiwygConfig,
        \Magento\Store\Model\System\Store $systemStore,
        array $data = []
    ) {
        $this->_wysiwygConfig = $wysiwygConfig;
        $this->_systemStore = $systemStore;
        parent::__construct($context, $registry, $formFactory, $data);
    }

    /**
     * Init form
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->setId('test_form');
        $this->setTitle(__('Item Information'));
    }

    /**
     * Prepare form
     *
     * @return $this
     */
    protected function _prepareForm()
    {
        $model = $this->_coreRegistry->registry('test_item');

        /** @var \Magento\Framework\Data\Form $form */
        $form = $this->_formFactory->create(
            ['data' => ['id' => 'edit_form', 'action' => $this->getData('action'), 'method' => 'post']]
        );

        $form->setHtmlIdPrefix('item_');

        $fieldset = $form->addFieldset(
            'base_fieldset',
            ['legend' => __('General Information'), 'class' => 'fieldset-wide']
        );

        if ($model->getId()) {
            $fieldset->addField('test_id', 'hidden', ['name' => 'test_id']);
        }

        $fieldset->addField(
            'name',
            'text',
            [
                'name' => 'name',
                'label' => __('Name'),
                'title' => __('Name'),
                'required' => true
            ]
        );

        $fieldset->addField(
            'email',
            'text',
            [
                'name' => 'email',
                'label' => __('Email'),
                'title' => __('Email'),
                'required' => true,
                'class' => 'validate-email'
            ]
        );

        $fieldset->addField(
            'is_active',
            'select',
            [
                'label' => __('Status'),
                'title' => __('Status'),
                'name' => 'is_active',
                'required' => true,
                'options' => ['1' => __('Enabled'), '0' => __('Disabled')]
            ]
        );
        if (!$model->getId()) {
            $model->setData('is_active', '1');
        }

        $fieldset->addField(
            'sort_order',
            'text',
            [
                'name' => 'sort_order',
                'label' => __('Sort Order'),
                'title' => __('Sort Order'),
                'required' => false
            ]
        );

        $form->setValues($model->getData());
        $form->setUseContainer(true);
        $this->setForm($form);

        return parent::_prepareForm();
    }
}

Az osztály _prepareForm() függvényében adjuk hozzá a szerkesztésre szánt mezőket, ami a mi esetünkben a name, email és sort_order mezők. Ezek mellett szerepel még a multistore kezelés szempontjából fontos store_id field is, illetve is_active field is, ami jelen esetben select típusú és a szerkesztés alatt álló elem státuszát hivatott beállítani.   A fent említett három osztállyal el is készítettük az adminisztrációs felületen történő szerkesztéshez szükséges fájlokat.

7) Controller-ek és layout létrehozása

Az editálás megvalósításához a fenti osztályokon kívül szükségünk lesz még a megfelelő controller osztályokra és layout fájlokra.   Az első osztályt az Aion/Test/Controller/Adminhtml/Test/ könyvtárban lévő NewAction.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

class NewAction extends \Aion\Test\Controller\Adminhtml\Test
{
    /**
     * @var \Magento\Backend\Model\View\Result\ForwardFactory
     */
    protected $resultForwardFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Registry $coreRegistry,
        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
    ) {
        $this->resultForwardFactory = $resultForwardFactory;
        parent::__construct($context, $coreRegistry);
    }

    /**
     * Create new item
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        /** @var \Magento\Framework\Controller\Result\Forward $resultForward */
        $resultForward = $this->resultForwardFactory->create();
        return $resultForward->forward('edit');
    }
}

Az osztály az új elemek létrehozására szolgál és lényegében az action függvénye (execute()) átirányít az Edit controller osztályra.   A következő lépésben létrehozzuk a szerkesztéshez szükséges controller-t. Az osztályt az Aion/Test/Controller/Adminhtml/Test/ könyvtárban lévő Edit.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

class Edit extends \Aion\Test\Controller\Adminhtml\Test
{
    /**
     * @var \Magento\Framework\View\Result\PageFactory
     */
    protected $resultPageFactory;

    /**
     * @param \Magento\Backend\App\Action\Context $context
     * @param \Magento\Framework\Registry $coreRegistry
     * @param \Magento\Framework\View\Result\PageFactory $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);
    }

    /**
     * Edit item
     *
     * @return \Magento\Framework\Controller\ResultInterface
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function execute()
    {
        // 1. Get ID and create model
        $id = $this->getRequest()->getParam('test_id');
        $model = $this->_objectManager->create('Aion\Test\Model\Test');

        // 2. Initial checking
        if ($id) {
            $model->load($id);
            if (!$model->getId()) {
                $this->messageManager->addError(__('This item no longer exists.'));
                /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
                $resultRedirect = $this->resultRedirectFactory->create();
                return $resultRedirect->setPath('*/*/');
            }
        }
        // 3. Set entered data if was error when we do save
        $data = $this->_objectManager->get('Magento\Backend\Model\Session')->getFormData(true);
        if (!empty($data)) {
            $model->setData($data);
        }

        // 4. Register model to use later in blocks
        $this->_coreRegistry->register('test_item', $model);

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

        // 5. Build edit form
        $this->initPage($resultPage)->addBreadcrumb(
            $id ? __('Edit Item') : __('New Item'),
            $id ? __('Edit Item') : __('New Item')
        );
        $resultPage->getConfig()->getTitle()->prepend(__('Items'));
        $resultPage->getConfig()->getTitle()->prepend($model->getId() ? $model->getName() : __('New Item'));
        return $resultPage;
    }
}

Az edit action(execute() függvény) első lépésben lekéri a test_id paramétert. Ezt követően inicializálja az Aion/Test/Model/Test modell osztályt. Amennyiben a test_id paraméternek van értéke, a modellt megpróbálja betöltelni az említett id-val. Sikertelen esetben hibaüzenet állít be, majd visszairányít. Ellenkező esetben a betöltött modellt a registry-ben tárolja ($this->_coreRegistry->register(’test_item’, $model)). Ezt olvassa ki a registry-ből a fent már említett form container osztály is, és használja fel. Végezetül létrehozza az oldalt ($resultPage), majd beállítja az oldal title paraméterét és breadcrumb-ot is.   A controller-hez tartozó layout fájlt az Aion/Test/view/adminhtml/layout/ könyvtárban lévő test_test_edit.xml fájlban valósítjuk meg:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <update handle="editor"/>
    <body>
        <referenceContainer name="content">
            <block class="Aion\Test\Block\Adminhtml\Test\Edit" name="test_test_edit"/>
        </referenceContainer>
    </body>
</page>

A következő lépés a mentés elkészítése. Az osztályt az Aion/Test/Controller/Adminhtml/Test/ könyvtárban lévő Save.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

class Save extends \Aion\Test\Controller\Adminhtml\Test
{
    /**
     * Save action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        // check if data sent
        $data = $this->getRequest()->getPostValue();
        if ($data) {
            $id = $this->getRequest()->getParam('test_id');
            $model = $this->_objectManager->create('Aion\Test\Model\Test')->load($id);
            if (!$model->getId() && $id) {
                $this->messageManager->addError(__('This item no longer exists.'));
                return $resultRedirect->setPath('*/*/');
            }

            // init model and set data

            $model->setData($data);

            // try to save it
            try {
                // save the data
                $model->save();
                // display success message
                $this->messageManager->addSuccess(__('You saved the item.'));
                // clear previously saved data from session
                $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData(false);

                // check if 'Save and Continue'
                if ($this->getRequest()->getParam('back')) {
                    return $resultRedirect->setPath('*/*/edit', ['test_id' => $model->getId()]);
                }
                // go to grid
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                // display error message
                $this->messageManager->addError($e->getMessage());
                // save data in session
                $this->_objectManager->get('Magento\Backend\Model\Session')->setFormData($data);
                // redirect to edit form
                return $resultRedirect->setPath('*/*/edit', ['test_id' => $this->getRequest()->getParam('test_id')]);
            }
        }
        return $resultRedirect->setPath('*/*/');
    }
}

A controller osztály első lépésben várja a korábban kialakított form által posztolt adatokat ($data = $this->getRequest()->getPostValue();). Amennyiben ez nem egy üres tömb, inicializálja az Aion/Test/Model/Test modell osztályt és ha létezik a paraméterként kapott test_id is (vagyis nem új objektum mentésére kerül sor), akkor betölti a megfelelő id-val. Ezt követően a post-ban kapott adatokat beállítja majd menti a modellt. Amennyiben mindezzel elkészültünk, akkor a korábban kialakított admin grid-ből (táblázat) új objektumokat tudunk hozzáadni és menteni, majd ezeket szerkeszteni. Még egy fontos controller van hátra, ami a törlést hivatott megvalósítani. Az osztályt az Aion/Test/Controller/Adminhtml/Test/ könyvtárban lévő Delete.php fájlban valósítjuk meg:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Aion\Test\Controller\Adminhtml\Test;

class Delete extends \Aion\Test\Controller\Adminhtml\Test
{
    /**
     * Delete action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
        $resultRedirect = $this->resultRedirectFactory->create();
        // check if we know what should be deleted
        $id = $this->getRequest()->getParam('test_id');
        if ($id) {
            try {
                // init model and delete
                $model = $this->_objectManager->create('Aion\Test\Model\Test');
                $model->load($id);
                $model->delete();
                // display success message
                $this->messageManager->addSuccess(__('You deleted the item.'));
                // go to grid
                return $resultRedirect->setPath('*/*/');
            } catch (\Exception $e) {
                // display error message
                $this->messageManager->addError($e->getMessage());
                // go back to edit form
                return $resultRedirect->setPath('*/*/edit', ['test_id' => $id]);
            }
        }
        // display error message
        $this->messageManager->addError(__('We can\'t find the item to delete.'));
        // go to grid
        return $resultRedirect->setPath('*/*/');
    }
}

A delete action (execute() függvény) első lépésben lekéri a test_id paramétert. Ezt követően inicializálja az Aion/Test/Model/Test model osztályt. Amennyiben a test_id paraméternek van értéke, a modellt megpróbálja betölteni az említett id-val, majd elvégzi a törlést.   Bízom benne, hogy ebben a kétrészes átfogó cikkben sikerült átadnom mindazt a tudnivalót, mellyel sikeresen hozhatsz létre te is egy saját modult a Magento 2 rendszerben, és állíthatsz be, illetve szerkeszthetsz különböző elemeket, fájlokat hozzá, mint pl. adatbázis tábla, modell, collection, block, admin táblázat, layout stb.   A cikk első része itt olvasható: Magento 2 modul fejlesztés lépésről lépésre – 1. rész

 

2774 válaszok
  1. best CBD oil says:

    I really like what you guys are up too. This sort
    of clever work and exposure! Keep up the wonderful works guys I’ve incorporated
    you guys to my personal blogroll.

  2. CBD capsules says:

    My brother suggested I would possibly like this web site.
    He was totally right. This publish truly made my
    day. You can not consider just how much time I had spent for
    this information! Thanks!

  3. best cbd oil for pain says:

    Write more, thats all I have to say. Literally, it seems as though you relied on the video to make your point.
    You clearly know what youre talking about,
    why waste your intelligence on just posting videos to your weblog
    when you could be giving us something enlightening to read?

  4. CBD gummies says:

    hey there and thank you for your information – I’ve certainly picked up
    something new from right here. I did however expertise a few technical issues using this
    website, as I experienced to reload the website lots of times
    previous to I could get it to load correctly.
    I had been wondering if your web hosting is OK?
    Not that I am complaining, but slow loading instances times will often affect your placement in google and can damage your high quality score
    if ads and marketing with Adwords. Well I’m adding this RSS to my e-mail
    and could look out for a lot more of your respective fascinating content.
    Ensure that you update this again soon.

  5. best CBD oil says:

    Hi there would you mind letting me know which web host you’re using?

    I’ve loaded your blog in 3 completely different browsers
    and I must say this blog loads a lot faster then most.
    Can you suggest a good internet hosting provider
    at a reasonable price? Thanks, I appreciate it!

  6. best CBD gummies says:

    Right here is the perfect website for anyone who would like to understand this topic.

    You understand a whole lot its almost hard to argue with you (not that I personally will
    need to…HaHa). You certainly put a fresh spin on a topic
    that’s been discussed for ages. Wonderful stuff, just wonderful!

  7. best CBD oil says:

    I have fun with, lead to I found exactly what
    I was looking for. You have ended my 4 day long hunt! God
    Bless you man. Have a great day. Bye

  8. best CBD oil says:

    Hey outstanding website! Does running a blog such as this require a massive amount work?
    I have absolutely no knowledge of programming but I had been hoping
    to start my own blog soon. Anyway, should you have any recommendations or techniques for new blog owners please share.

    I understand this is off topic however I just needed to ask.
    Thanks a lot!

  9. best CBD oil says:

    I’m impressed, I must say. Seldom do I encounter a blog that’s both equally educative and entertaining, and without a doubt, you have hit the nail on the
    head. The problem is something that too few folks
    are speaking intelligently about. I am very happy
    I stumbled across this during my search for something regarding this.

  10. best CBD oil for sleep says:

    Admiring the dedication you put into your site and in depth information you present.

    It’s good to come across a blog every once in a
    while that isn’t the same unwanted rehashed information.
    Great read! I’ve bookmarked your site and I’m adding your RSS feeds to my Google account.

  11. sleepy baby yoda says:

    Hey there! I just wanted to ask if you ever have any issues with hackers?
    My last blog (wordpress) was hacked and I ended up losing a few months of hard work due to no back up.

    Do you have any solutions to protect against hackers?

  12. CBD oil says:

    Hello! This is kind of off topic but I need some guidance from an established blog.
    Is it very difficult to set up your own blog? I’m not very techincal but I can figure things out pretty fast.
    I’m thinking about creating my own but I’m not sure
    where to start. Do you have any ideas or suggestions? Thanks

    Here is my page :: CBD oil

  13. best CBD oil UK says:

    I’m impressed, I must say. Seldom do I encounter a blog that’s
    both equally educative and entertaining, and without a doubt, you’ve hit the nail on the head.
    The issue is something too few folks are speaking intelligently about.
    Now i’m very happy I found this in my search for something regarding this.

    Also visit my homepage … best CBD oil UK

  14. CBD oil UK says:

    I enjoy what you guys tend to be up too. This sort of clever work
    and coverage! Keep up the good works guys I’ve added you guys to
    our blogroll.

    Feel free to surf to my webpage CBD oil UK

  15. buy CBD oil says:

    Hey just wanted to give you a quick heads up. The text in your article seem to be running off the screen in Opera.
    I’m not sure if this is a format issue or something to do with browser compatibility but I thought I’d
    post to let you know. The style and design look great though!

    Hope you get the problem resolved soon. Thanks

    Feel free to visit my blog :: buy CBD oil

  16. CBD says:

    I’m really enjoying the theme/design of your weblog.
    Do you ever run into any web browser compatibility issues?
    A small number of my blog audience have complained about
    my site not working correctly in Explorer but looks great in Safari.
    Do you have any solutions to help fix this problem?

    Here is my web blog; CBD

  17. web hosting reviews says:

    Thank you for the auspicious writeup. It in fact was a amusement account it.
    Look advanced to far added agreeable from you! However, how could we communicate?

  18. website hosting says:

    You could definitely see your skills in the work you write.

    The world hopes for more passionate writers like you who aren’t afraid to mention how
    they believe. Always go after your heart.

  19. Revue Thommen Watch says:

    An outstanding share! I have just forwarded this onto a co-worker who has been doing a little
    homework on this. And he in fact bought me breakfast because I stumbled upon it for
    him… lol. So let me reword this…. Thanks for the meal!!
    But yeah, thanx for spending some time to talk about this issue here
    on your web site.

    Have a look at my homepage … Revue Thommen Watch

  20. Resurge review 2020 says:

    Definitely imagine that that you said. Your favorite reason seemed
    to be at the net the easiest thing to take into accout of.

    I say to you, I definitely get annoyed whilst people consider worries that they plainly do not recognise about.
    You managed to hit the nail upon the highest as well as defined out the entire
    thing with no need side-effects , folks can take a
    signal. Will probably be back to get more. Thanks

    Also visit my web-site; Resurge review 2020

  21. love spells that work says:

    Aw, this was a really nice post. In idea I would like to put in writing like this additionally ? taking time and actual effort to make a very good article? but what can I say? I procrastinate alot and by no means seem to get something done.

  22. wooden garage doors Los Angeles says:

    Wonderful goods from you, man. I have bear in mind your stuff prior to and you
    are simply too wonderful. I really like what you’ve received here, really like what you are stating
    and the way in which by which you say it. You’re making it entertaining and you still take
    care of to stay it wise. I cant wait to read far more from you.

    That is actually a tremendous website.

    Feel free to surf to my site – wooden garage doors Los Angeles

  23. Crystal Water Bottle says:

    After study a few of the blog posts on your website now, and I truly like your way of blogging. I bookmarked it to my bookmark website list and will be checking back soon. Pls check out my web site as well and let me know what you think.

  24. Crystal Water Bottle says:

    There are certainly a lot of details like that to take into consideration. That is a great point to bring up. I offer the thoughts above as general inspiration but clearly there are questions like the one you bring up where the most important thing will be working in honest good faith. I don?t know if best practices have emerged around things like that, but I am sure that your job is clearly identified as a fair game. Both boys and girls feel the impact of just a moment?s pleasure, for the rest of their lives.

  25. Poker Indonesia says:

    Hey! I know this is kinda off topic but I was wondering which blog
    platform are you using for this website? I’m getting sick and tired of WordPress because I’ve had problems with hackers and I’m looking at options for another platform.
    I would be great if you could point me in the direction of a good
    platform.

    Feel free to surf to my homepage: Poker Indonesia

  26. cheap flights says:

    May I simply say what a comfort to uncover someone that really
    understands what they are talking about over the internet.

    You actually know how to bring a problem to light and make it important.
    A lot more people really need to look at this and understand this side of your story.
    I was surprised you are not more popular since you certainly have the gift.

  27. cheap flights says:

    Hi there! I’m at work browsing your blog from my new apple iphone!

    Just wanted to say I love reading through your blog and look forward to all your posts!
    Carry on the great work! cheap flights 3aN8IMa

  28. cheap flights says:

    Greetings from California! I’m bored to tears at work so I decided to browse your site on my
    iphone during lunch break. I really like the information you provide here and can’t wait
    to take a look when I get home. I’m amazed at how quick your blog loaded
    on my mobile .. I’m not even using WIFI, just 3G ..
    Anyways, awesome blog!

  29. marquee says:

    I don’t even know how I ended up here, however I assumed this publish
    was good. I don’t recognise who you’re however definitely
    you are going to a famous blogger if you happen to are not already.
    Cheers!

    Feel free to visit my web-site :: marquee

  30. cheap flights says:

    Thanks for some other great post. The place else may
    anyone get that kind of information in such an ideal way of writing?
    I have a presentation next week, and I’m at the look for such information. cheap flights 32hvAj4

  31. cheap flights says:

    Everyone loves what you guys tend to be up too. Such clever work and reporting!
    Keep up the superb works guys I’ve included you guys to my personal blogroll.

  32. 3v3XxmoJ3Ub says:

    790911 928232Spot up for this write-up, I in fact feel this exceptional internet site requirements a good deal far more consideration. Ill far more likely be once once again to read considerably far more, thank you that data. 387241

  33. med PPE Canada says:

    Hello! I just would like to give a huge thumbs up for the great info you have here on this post. I will be coming back to your blog for more soon.

  34. cheap flights says:

    Hi there! This post could not be written any better!
    Reading this post reminds me of my previous room mate!
    He always kept talking about this. I will forward this page to him.
    Pretty sure he will have a good read. Thanks for
    sharing!

  35. cheap flights says:

    I’ll right away grasp your rss as I can’t find your e-mail subscription link or newsletter service.
    Do you have any? Kindly permit me recognise in order that
    I could subscribe. Thanks.

  36. black mass says:

    It is appropriate time to make some plans for the future and it is time to be happy.

    I’ve read this post and if I could I wish to suggest you few interesting
    things or suggestions. Maybe you could write next articles
    referring to this article. I wish to read even more things
    about it!

  37. black mass says:

    After I initially commented I appear to have clicked the -Notify me when new comments are added-
    checkbox and now whenever a comment is added I get four emails with the same comment.

    Is there a means you are able to remove me from that
    service? Cheers!

  38. Alden Morowski says:

    Excellent blog right here! Also your web site lots up very fast! What host are you using? Can I get your affiliate link for your host? I wish my website loaded up as fast as yours lol|

  39. kadikoy escort says:

    Excellent way of describing, and pleasant
    article to get information concerning my presentation subject matter,
    which i am going to deliver in institution of higher education.

    Also visit my website kadikoy escort

  40. sex says:

    always i used to read smaller posts which also clear their motive,
    and that is also happening with this post which I am reading now.

    Have a look at my web page – sex

  41. VOERING says:

    Quality content is the main to invite the people to pay a
    quick visit the site, that’s what this web page
    is providing.

    Here is my blog post; VOERING

  42. bayan escort says:

    Cool blog! Is your theme custom made or did you download it from somewhere? A design like yours with a few simple adjustements would really make my blog jump out. Please let me know where you got your design. Bless you

  43. visa 482 says:

    Great site. A lot of helpful info here. I’m sending it to several pals ans additionally sharing in delicious.
    And certainly, thanks on your effort!

    Feel free to visit my web site … visa 482

  44. Internetmarketing winsum says:

    Howdy I am so delighted I found your website, I really found you by error,
    while I was looking on Google for something else,
    Anyways I am here now and would just like to say thank you
    for a marvelous post and a all round enjoyable blog (I also love the theme/design), I
    don’t have time to go through it all at the moment but I have saved
    it and also added in your RSS feeds, so when I have time I will be back to
    read much more, Please do keep up the superb job.

    My web blog: Internetmarketing winsum

  45. SEO woerdense verlaat says:

    I think what you published was very reasonable. However, think about this, suppose you wrote a catchier post title?
    I ain’t suggesting your content isn’t solid., but what if you added something that grabbed people’s attention?
    I mean Magento 2 modul fejlesztés lépésről lépésre –
    2. rész – aionhill.com is a little boring.

    You might peek at Yahoo’s home page and see how they write article titles to grab viewers interested.
    You might add a related video or a pic or two to get readers excited about everything’ve got to say.
    Just my opinion, it could bring your blog a little bit more interesting.

    My homepage; SEO woerdense verlaat

  46. RV Service says:

    My spouse and I stumbled over here by a different web page and thought I may as well check things out.

    I like what I see so now i’m following you. Look forward to looking at your web
    page yet again.

    Have a look at my web site … RV Service

  47. RV Shop Near Me says:

    Thanks for the marvelous posting! I quite enjoyed reading it, you happen to be a great author.
    I will be sure to bookmark your blog and will eventually come back later in life.
    I want to encourage you to definitely continue your great posts, have a nice morning!

    My site … RV Shop Near Me

  48. gorredijk Fryslan says:

    I am extremely impressed with your writing skills as well as with the layout on your blog.
    Is this a paid theme or did you modify it yourself? Anyway keep up the nice quality writing, it’s rare
    to see a nice blog like this one today.

    My web blog :: gorredijk Fryslan

  49. Bedrijfsuitje Gelderland says:

    Hello I am so delighted I found your webpage,
    I really found you by mistake, while I was searching on Digg for something
    else, Nonetheless I am here now and would just like to say
    thank you for a incredible post and a all round entertaining blog (I also love
    the theme/design), I don’t have time to read through it all at the moment but I have
    book-marked it and also included your RSS feeds, so when I
    have time I will be back to read more, Please do keep up the
    awesome job.

    Here is my page: Bedrijfsuitje Gelderland

  50. Wendolyn Braddy says:

    The next time I read a blog, Hopefully it won’t disappoint me as much as this one. After all, Yes, it was my choice to read through, but I genuinely thought you would probably have something useful to talk about. All I hear is a bunch of complaining about something that you could fix if you were not too busy seeking attention.

  51. Kevin David says:

    Itís actually a great and helpful piece of info. Iím glad that you shared this useful information with us. Please keep us informed like this. Thanks for sharing.

  52. Markus Bork says:

    I’d like to thank you for the efforts you have put in writing this site. I am hoping to view the same high-grade blog posts from you in the future as well. In fact, your creative writing abilities has inspired me to get my very own blog now ;)

  53. Colin Sheltra says:

    Great site you’ve got here.. It’s hard to find excellent writing like yours these days. I seriously appreciate individuals like you! Take care!!

  54. Casey Monreal says:

    I was very pleased to uncover this great site. I need to to thank you for ones time for this fantastic read!! I definitely savored every bit of it and I have you bookmarked to look at new things on your website.

  55. Kandice Yarman says:

    You are so cool! I don’t believe I’ve read anything like that before. So great to find someone with original thoughts on this issue. Seriously.. many thanks for starting this up. This site is one thing that is required on the web, someone with some originality!

  56. Doretha Halmes says:

    I was extremely pleased to discover this web site. I want to to thank you for your time due to this wonderful read!! I definitely appreciated every part of it and I have you saved as a favorite to see new stuff on your blog.

  57. Erik Weible says:

    Hi, I think your site may be having internet browser compatibility problems. When I take a look at your blog in Safari, it looks fine however, if opening in Internet Explorer, it has some overlapping issues. I just wanted to give you a quick heads up! Other than that, great site!

  58. Ignacio Kelling says:

    An impressive share! I have just forwarded this onto a co-worker who has been doing a little research on this. And he in fact ordered me lunch due to the fact that I discovered it for him… lol. So allow me to reword this…. Thank YOU for the meal!! But yeah, thanx for spending the time to discuss this subject here on your internet site.

  59. Wei Mayhall says:

    Aw, this was an incredibly nice post. Taking a few minutes and actual effort to generate a superb article… but what can I say… I procrastinate a whole lot and never seem to get anything done.

  60. Edison Bounds says:

    I was excited to uncover this site. I need to to thank you for ones time due to this fantastic read!! I definitely liked every little bit of it and i also have you saved as a favorite to check out new things in your website.

  61. Jeanice Picketpin says:

    I’m more than happy to find this great site. I want to to thank you for ones time due to this fantastic read!! I definitely really liked every little bit of it and I have you bookmarked to check out new things on your website.

  62. Nadia Campusano says:

    After looking over a few of the blog posts on your website, I seriously appreciate your technique of writing a blog. I added it to my bookmark website list and will be checking back in the near future. Please check out my website as well and tell me what you think.

  63. Roberto Klingen says:

    An outstanding share! I have just forwarded this onto a coworker who had been conducting a little research on this. And he in fact ordered me breakfast simply because I found it for him… lol. So let me reword this…. Thank YOU for the meal!! But yeah, thanx for spending some time to talk about this issue here on your site.

  64. Winter Magg says:

    I truly love your website.. Very nice colors & theme. Did you build this web site yourself? Please reply back as I’m looking to create my own website and want to learn where you got this from or just what the theme is called. Cheers!

  65. Nigel Molenda says:

    Hi, I do believe this is an excellent site. I stumbledupon it ;) I am going to revisit once again since i have saved as a favorite it. Money and freedom is the best way to change, may you be rich and continue to guide others.

  66. Légalisation Cuba says:

    Terrific work! This is the type of info that are meant to be shared
    across the internet. Shame on Google for now not positioning this post upper!
    Come on over and talk over with my website . Thank you =)

    Also visit my homepage – Légalisation Cuba

  67. Légalisation Tonga says:

    Just want to say your article is as astounding. The clearness to your put up is simply great and that i can assume you’re knowledgeable in this
    subject. Fine together with your permission let me to grab your feed to stay up to date with drawing close post.
    Thank you one million and please keep up the rewarding work.

    My web blog; Légalisation Tonga

  68. Norberto Dozier says:

    I need to to thank you for this great read!! I absolutely loved every little bit of it. I’ve got you book-marked to check out new things you post…

  69. Légalisation Brunei says:

    Hi there, i read your blog from time to time and i own a similar one and i was just curious if you get a lot of
    spam comments? If so how do you reduce it, any plugin or anything you can recommend?
    I get so much lately it’s driving me insane so any assistance is very much
    appreciated.

    My web page: Légalisation Brunei

  70. Légalisation Croatie says:

    Oh my goodness! Awesome article dude! Many thanks, However I am encountering troubles with your RSS.
    I don’t know why I am unable to join it. Is there anybody else getting the same RSS problems?
    Anyone who knows the solution can you kindly respond?
    Thanx!!

    Take a look at my site Légalisation Croatie

  71. Légalisation Oman says:

    Howdy! I know this is kinda off topic however I’d figured I’d ask.
    Would you be interested in trading links or maybe guest authoring a blog article
    or vice-versa? My site discusses a lot of the same topics as yours and I feel we could greatly benefit from
    each other. If you might be interested feel free to
    shoot me an email. I look forward to hearing from you!
    Fantastic blog by the way!

    Here is my webpage … Légalisation Oman

  72. Car Washer says:

    Your style is unique compared to other folks I’ve read stuff from.
    Many thanks for posting when you have the opportunity, Guess
    I’ll just bookmark this blog.

    my page Car Washer

  73. mua hộp quà sinh nhật ở đâu says:

    Great goods from you, man. I have understand your stuff previous to and you are just too
    wonderful. I really like what you’ve acquired here, really like what you’re saying and the way
    in which you say it. You make it enjoyable and you still take care of to keep it
    sensible. I can’t wait to read much more
    from you. This is actually a wonderful web site.

    my blog post – mua hộp quà sinh nhật ở đâu

  74. Caleb Yanish says:

    Oh my goodness! Incredible article dude! Many thanks, However I am having troubles with your RSS. I don’t understand the reason why I cannot join it. Is there anybody having the same RSS issues? Anyone who knows the answer will you kindly respond? Thanks!!

  75. Diane Fuschetto says:

    Your style is so unique in comparison to other people I’ve read stuff from. Many thanks for posting when you have the opportunity, Guess I will just bookmark this site.

  76. canada prescriptions says:

    Hiya very cool blog!! Guy .. Excellent .. Wonderful ..
    I will bookmark your web site and take the feeds also?
    I am satisfied to find a lot of helpful information right here within the post, we
    want develop extra techniques on this regard, thank you
    for sharing. . . . . .

    Feel free to visit my web-site: canada prescriptions

  77. discuss says:

    Greetings from Florida! I’m bored to death at work so I decided to browse your blog on my
    iphone during lunch break. I love the knowledge you provide here
    and can’t wait to take a look when I get home. I’m shocked at how fast your blog loaded on my phone ..
    I’m not even using WIFI, just 3G .. Anyways, amazing site!

    Feel free to visit my site … discuss

  78. discuss says:

    Its like you read my mind! You seem to know so much about this, like you wrote the book in it or something.
    I think that you can do with some pics to drive the message home a little bit,
    but instead of that, this is wonderful blog.

    A fantastic read. I will definitely be back.

    Stop by my webpage – discuss

  79. Lenna Griffieth says:

    Excellent blog you have got here.. It’s difficult to find high quality writing like yours nowadays. I seriously appreciate individuals like you! Take care!!

  80. Olen Cruse says:

    Greetings! Very helpful advice in this particular post! It is the little changes that make the most important changes. Many thanks for sharing!

  81. Oscar Corker says:

    Right here is the right web site for anyone who really wants to understand this topic. You realize so much its almost hard to argue with you (not that I actually would want to…HaHa). You certainly put a new spin on a subject that’s been discussed for a long time. Great stuff, just excellent!

  82. Staci Bary says:

    I blog frequently and I truly appreciate your information. This great article has truly peaked my interest. I am going to take a note of your site and keep checking for new details about once per week. I subscribed to your Feed as well.

  83. film says:

    There is certainly a lot to learn about this subject.
    I really like all of the points you’ve made.

    Here is my blog – film

  84. Pa Knudtson says:

    An outstanding share! I have just forwarded this onto a colleague who had been conducting a little research on this. And he actually ordered me dinner due to the fact that I found it for him… lol. So let me reword this…. Thank YOU for the meal!! But yeah, thanks for spending time to talk about this topic here on your web site.

  85. Vincent Perlow says:

    A fascinating discussion is worth comment. I do believe that you should publish more on this subject, it may not be a taboo subject but typically people do not speak about these subjects. To the next! Best wishes!!

  86. Suzann Lipka says:

    An outstanding share! I’ve just forwarded this onto a co-worker who has been conducting a little homework on this. And he actually bought me breakfast due to the fact that I found it for him… lol. So allow me to reword this…. Thank YOU for the meal!! But yeah, thanks for spending the time to talk about this subject here on your web site.

  87. Normand Aronson says:

    Greetings, There’s no doubt that your website could possibly be having internet browser compatibility issues. When I take a look at your web site in Safari, it looks fine however, when opening in I.E., it has some overlapping issues. I merely wanted to give you a quick heads up! Apart from that, excellent site!

  88. Seymour Bruington says:

    A fascinating discussion is worth comment. There’s no doubt that that you should publish more on this topic, it might not be a taboo matter but typically folks don’t discuss such issues. To the next! Cheers!!

  89. Scott Ryan says:

    I love making documentaries, hosting them, and generally adventuring into the unknown. I love it so much I made the first modern series to chronicle the work of activists. It is called Manifesto. See it and more of my work.

  90. Javier Firoozbakht says:

    Can I simply just say what a comfort to uncover an individual who really knows what they are discussing on the net. You certainly understand how to bring an issue to light and make it important. A lot more people must look at this and understand this side of the story. It’s surprising you’re not more popular since you surely have the gift.

  91. Elene Htwe says:

    I’d like to thank you for the efforts you’ve put in writing this blog. I am hoping to check out the same high-grade blog posts by you in the future as well. In fact, your creative writing abilities has inspired me to get my own, personal blog now ;)

  92. plus solar says:

    Hello there, I found your blog via Google while searching for a related topic, your site came up, it looks good. I’ve bookmarked it in my google bookmarks.

  93. Margarito Utsey says:

    An outstanding share! I’ve just forwarded this onto a coworker who was doing a little research on this. And he in fact ordered me dinner due to the fact that I stumbled upon it for him… lol. So allow me to reword this…. Thanks for the meal!! But yeah, thanks for spending the time to talk about this topic here on your website.

  94. swimsuit says:

    I have been exploring for a little for any high-quality articles or blog posts on this sort of space . Exploring in Yahoo I eventually stumbled upon this web site. Studying this info So i?¦m satisfied to convey that I have a very just right uncanny feeling I found out exactly what I needed. I such a lot indisputably will make sure to don?¦t overlook this website and provides it a glance on a relentless basis.

  95. Rapshonig kaufen says:

    Hello, Neat post. There’s a problem along with your web site in internet explorer, might check this?K IE nonetheless is the marketplace leader and a good section of other people will pass over your magnificent writing because of this problem.

  96. energy iot says:

    This is the right blog for anyone who wants to find out about this topic. You realize so much its almost hard to argue with you (not that I actually would want…HaHa). You definitely put a new spin on a topic thats been written about for years. Great stuff, just great!

  97. Darla Reisch says:

    I’m pretty pleased to discover this page. I need to to thank you for ones time just for this fantastic read!! I definitely loved every little bit of it and i also have you book-marked to look at new information in your site.

  98. Lucien Johndrow says:

    Aw, this was an exceptionally nice post. Taking a few minutes and actual effort to create a great article… but what can I say… I hesitate a lot and don’t seem to get nearly anything done.

  99. 9anime to says:

    I truly enjoy looking through on this web site, it has superb posts. “One should die proudly when it is no longer possible to live proudly.” by Friedrich Wilhelm Nietzsche.

  100. RV Tires says:

    Way cool! Some very valid points! I appreciate you writing this post and also the rest of the site is also really good.

  101. RV Interior Designer says:

    I’m amazed, I have to admit. Rarely do I encounter a blog that’s both educative and amusing, and let me tell you, you have hit the nail on the head. The issue is an issue that not enough men and women are speaking intelligently about. I’m very happy I stumbled across this in my search for something regarding this.

  102. Parts California says:

    Aw, this was an exceptionally nice post. Taking the time and actual effort to create a great article… but what can I say… I put things off a whole lot and don’t seem to get anything done.

  103. Sandy Rubenstein says:

    I just like the helpful info you provide to your articles. I will bookmark your weblog and take a look at again right here frequently. I’m relatively certain I will be informed many new stuff proper right here! Best of luck for the next!|

  104. have a peek here says:

    Can I just say what a reduction to seek out someone who actually is aware of what theyre talking about on the internet. You positively know tips on how to bring a problem to mild and make it important. Extra folks need to learn this and perceive this side of the story. I cant believe youre no more common since you undoubtedly have the gift.

  105. rv service and repair near me says:

    I’m impressed, I must say. Seldom do I encounter a blog that’s equally educative and engaging, and without a doubt, you’ve hit the nail on the head. The issue is an issue that not enough people are speaking intelligently about. I’m very happy I stumbled across this during my search for something concerning this.

  106. Shower Repair says:

    An intriguing discussion is definitely worth comment. I do believe that you need to write more about this subject, it may not be a taboo matter but generally people do not talk about these issues. To the next! Cheers!!

  107. affiliate marketing price in cebu says:

    Howdy very cool web site!! Man .. Excellent .. Amazing .. I’ll bookmark your site and take the feeds also…I am satisfied to seek out so many useful info right here within the submit, we need develop extra techniques in this regard, thanks for sharing. . . . . .

  108. Semi Truck Repair says:

    Oh my goodness! Awesome article dude! Many thanks, However I am going through difficulties with your RSS. I don’t know why I am unable to join it. Is there anyone else having similar RSS problems? Anyone who knows the answer can you kindly respond? Thanx!!

  109. RV Outside Entertainment Center says:

    I was excited to find this great site. I want to to thank you for ones time just for this wonderful read!! I definitely savored every little bit of it and i also have you saved to fav to check out new stuff in your website.

  110. What Is The Process amazon fba retail arbitrage says:

    Hi there I am so thrilled I found your blog page, I really found you by mistake, while I was browsing on Digg for something else, Anyhow I am here now and would just like to say thanks for a incredible post and a all round enjoyable blog (I also love the theme/design), I don’t have time to read through it all at the moment but I have saved it and also included your RSS feeds, so when I have time I will be back to read a great deal more, Please do keep up the excellent work.

  111. Ann Dawood says:

    fantastic post, very informative. I wonder why the other experts of this sector do not understand this. You must proceed your writing. I am confident, you’ve a great readers’ base already!

  112. solar company in melaka says:

    Youre so cool! I dont suppose Ive read anything like this before. So good to seek out someone with some unique thoughts on this subject. realy thanks for starting this up. this web site is one thing that is needed on the net, somebody with just a little originality. helpful job for bringing one thing new to the internet!

  113. RV Plumbing says:

    An impressive share! I’ve just forwarded this onto a coworker who was conducting a little homework on this. And he actually bought me lunch because I discovered it for him… lol. So let me reword this…. Thanks for the meal!! But yeah, thanks for spending the time to talk about this subject here on your website.

  114. leap year ซับไทย says:

    Hello, Neat post. There is a problem along with your website in internet explorer, may test this… IE still is the market leader and a huge portion of other folks will pass over your magnificent writing because of this problem.

  115. RV Remodeling & RV Furniture Cahuenga Pass CA says:

    This is the perfect website for anybody who really wants to find out about this topic. You understand so much its almost hard to argue with you (not that I personally will need to…HaHa). You certainly put a fresh spin on a subject which has been written about for decades. Wonderful stuff, just excellent!

  116. RV Towing Service says:

    Having read this I thought it was really enlightening. I appreciate you finding the time and energy to put this informative article together. I once again find myself personally spending way too much time both reading and posting comments. But so what, it was still worthwhile!

  117. RV Shower Parts says:

    This is a good tip particularly to those fresh to the blogosphere. Brief but very precise information… Many thanks for sharing this one. A must read article!

  118. solar company in melaka says:

    I think this is one of the most vital info for me. And i’m glad reading your article. But wanna remark on few general things, The site style is ideal, the articles is really excellent : D. Good job, cheers

  119. Haulmark Car Trailer Collision Repair Shop Near Me California says:

    May I simply just say what a comfort to find somebody who actually knows what they’re talking about on the internet. You certainly understand how to bring a problem to light and make it important. More and more people should read this and understand this side of the story. It’s surprising you’re not more popular because you surely possess the gift.

  120. Thor Aspire Collision Repair Shop Near Me California says:

    May I simply say what a comfort to uncover somebody who really knows what they’re talking about over the internet. You actually realize how to bring an issue to light and make it important. More and more people really need to check this out and understand this side of the story. It’s surprising you’re not more popular because you certainly possess the gift.

  121. RV Headlights says:

    I blog quite often and I seriously thank you for your content. This great article has really peaked my interest. I am going to bookmark your website and keep checking for new information about once per week. I opted in for your Feed too.

  122. RV Led Lighting says:

    Hey there! I just would like to give you a big thumbs up for your excellent info you have got here on this post. I’ll be coming back to your site for more soon.

  123. 58 Cheesy Best Pick Up Lines for Tinder That Really Work says:

    What i do not realize is in fact how you’re now not really a lot more smartly-liked than you might be now. You’re very intelligent. You already know therefore significantly in the case of this matter, made me in my view imagine it from numerous varied angles. Its like men and women don’t seem to be fascinated except it is something to accomplish with Woman gaga! Your own stuffs outstanding. At all times care for it up!

  124. dđồ thể thao trẻ em says:

    I just couldn’t leave your website before suggesting that I actually loved the usual info a person supply for your guests? Is going to be back often to investigate cross-check new posts

  125. cai win tan nha says:

    Hmm it seems like your website ate my first comment (it was super long) so I guess I’ll just sum it up what I had written and say, I’m thoroughly enjoying your blog. I as well am an aspiring blog blogger but I’m still new to everything. Do you have any tips and hints for novice blog writers? I’d certainly appreciate it.

  126. หวยลาว says:

    It is really a nice and useful piece of information. I am glad that you shared this helpful info with us. Please keep us informed like this. Thanks for sharing.

  127. Long Beach says:

    I’m excited to discover this website. I wanted to thank you for ones time for this particularly wonderful read!! I definitely savored every part of it and I have you bookmarked to check out new information in your web site.

  128. nhà cái số 1 says:

    Wonderful post but I was wondering if you could write a litte more on this subject? I’d be very thankful if you could elaborate a little bit further. Thanks!

  129. Herschel Ropac says:

    hi!,I love your writing very much! percentage we communicate extra about your post on AOL? I require an expert on this house to resolve my problem. May be that is you! Taking a look forward to peer you.

  130. Buy passports says:

    I’m impressed, I have to say. Really rarely do I encounter a blog that’s each educative and entertaining, and let me let you know, you might have hit the nail on the head. Your concept is outstanding; the problem is one thing that not enough individuals are talking intelligently about. I am very pleased that I stumbled throughout this in my seek for something relating to this.

  131. khuc ca yeu cuoc doi says:

    Hi there, I discovered your web site by way of Google whilst searching for a related topic, your website came up, it appears great. I have bookmarked it in my google bookmarks.

  132. VPS Hosting Provider says:

    I like what you guys are up also. Such intelligent work and reporting! Keep up the excellent works guys I?¦ve incorporated you guys to my blogroll. I think it will improve the value of my web site :)

  133. F1 grandprix nieuws says:

    Great blog! Do you have any tips and hints for aspiring writers?
    I’m planning to start my own blog soon but I’m a little
    lost on everything. Would you advise starting with a free platform like WordPress or go for
    a paid option? There are so many options out there that I’m completely confused
    .. Any ideas? Many thanks!

    My web site: F1 grandprix nieuws

  134. RV Remodeling Companies says:

    You’re so cool! I do not suppose I have read anything like that before. So nice to discover somebody with a few genuine thoughts on this subject. Really.. many thanks for starting this up. This web site is one thing that is needed on the internet, someone with a little originality!

  135. Porn55 says:

    Porn55 draw knew bred ham busy his hour. Ask agreed answer rather joy nature admire wisdom. Porn55 age depending bed led therefore sometimes preserved exquisite she. An fail up so shot leaf wise in. Minuter highest his arrived for put and. Hopes lived by rooms oh in no death house. Contented direction september but end led excellent ourselves may. Ferrars few arrival his offered not charmed you. Offered anxious respect or he. On three thing chief years in money arise of.

  136. Watch Movies Online Reddit says:

    I think this is one of the such a lot vital information for me. And i’m satisfied reading your article. But wanna observation on few basic issues, The website style is wonderful, the articles is really great : D. Just right activity, cheers

  137. เช็คล็อตเตอรี่ says:

    Along with every little thing which seems to be developing inside this specific subject matter, many of your opinions happen to be very refreshing. Even so, I am sorry, but I can not subscribe to your entire idea, all be it exciting none the less. It appears to everyone that your remarks are generally not completely validated and in actuality you are yourself not even entirely confident of your point. In any event I did appreciate reading through it.

  138. Ward Lipovsky says:

    I absolutely love your website.. Great colors & theme. Did you build this web site yourself? Please reply back as I’m planning to create my own site and would love to find out where you got this from or exactly what the theme is named. Appreciate it!

  139. Lesley Caney says:

    I blog frequently and I truly appreciate your content. This article has really peaked my interest. I am going to book mark your blog and keep checking for new details about once per week. I subscribed to your Feed as well.

  140. tenis atacado says:

    When I originally commented I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get four e-mails with the same comment. Is there any way you can remove me from that service? Thanks a lot!

  141. Serena Holey says:

    Greetings! Very useful advice in this particular post! It is the little changes that make the most significant changes. Many thanks for sharing!

  142. Wilber Crandal says:

    certainly like your website however you have to check the spelling on several of your posts. Many of them are rife with spelling problems and I find it very troublesome to inform the truth however I will surely come again again.

  143. Fritz Muzyka says:

    An interesting discussion is definitely worth comment. I believe that you should publish more about this subject matter, it might not be a taboo subject but typically folks don’t speak about these topics. To the next! Kind regards!!

  144. here says:

    You have made some good points there. I looked on the net to learn more about the issue and found most individuals will go along with your views on this website.

  145. Shonta Bumby says:

    A fascinating discussion is worth comment. There’s no doubt that that you ought to publish more on this topic, it might not be a taboo matter but usually people do not discuss such issues. To the next! All the best!!

  146. Curso de Celular says:

    I haven?¦t checked in here for a while because I thought it was getting boring, but the last several posts are good quality so I guess I will add you back to my everyday bloglist. You deserve it my friend :)

  147. Mitch Balchunas says:

    I’m amazed, I have to admit. Seldom do I come across a blog that’s both equally educative and amusing, and let me tell you, you have hit the nail on the head. The problem is something that too few men and women are speaking intelligently about. I am very happy I stumbled across this in my search for something regarding this.

  148. Adrian Twiet says:

    It is really a great and helpful piece of information. I am glad that you shared this useful info with us. Please keep us up to date like this. Thank you for sharing.

  149. 구찌출장 says:

    Aw, this was an extremely nice post. Taking the time and actual effort to make a superb articleÖ but what can I sayÖ I put things off a whole lot and don’t seem to get anything done.

  150. Courtney Bostrom says:

    Appreciating the commitment you put into your site and detailed information you offer. It’s great to come across a blog every once in a while that isn’t the same outdated rehashed information. Excellent read! I’ve saved your site and I’m including your RSS feeds to my Google account.

  151. Watching Movies Online says:

    Generally I don’t learn post on blogs, but I wish to say that this write-up very pressured me to check out and do it! Your writing taste has been surprised me. Thanks, quite nice article.

  152. Mario Mihalik says:

    Aw, this was an exceptionally nice post. Spending some time and actual effort to generate a superb article… but what can I say… I put things off a whole lot and never seem to get anything done.

  153. Where Cani Watch Movies Online says:

    That is the right weblog for anyone who needs to find out about this topic. You notice a lot its virtually laborious to argue with you (not that I truly would need…HaHa). You definitely put a brand new spin on a topic thats been written about for years. Great stuff, just nice!

  154. Silas Broe says:

    Wonderful work! This is the type of information that should be shared around the internet. Shame on Google for not positioning this post higher! Come on over and visit my website . Thanks =)

  155. Stanton Slotemaker says:

    I needed to thank you for this very good read!! I absolutely loved every little bit of it. I’ve got you bookmarked to check out new things you post…

  156. Hindi Movies Online Free says:

    I have not checked in here for a while as I thought it was getting boring, but the last several posts are great quality so I guess I’ll add you back to my everyday bloglist. You deserve it my friend :)

  157. Aaron Chattin says:

    Oh my goodness! Incredible article dude! Thank you, However I am experiencing issues with your RSS. I don’t know the reason why I cannot join it. Is there anybody else getting identical RSS issues? Anyone who knows the answer will you kindly respond? Thanx!!

  158. Daftar NagaPoker says:

    I really like your blog.. very nice colors & theme. Did you design this website yourself or did you hire someone to do it for you? Plz reply as I’m looking to construct my own blog and would like to know where u got this from. thank you

  159. Emmanuel Fosser says:

    Woah! I’m really loving the template/theme of this blog. It’s simple, yet effective. A lot of times it’s very hard to get that “perfect balance” between superb usability and visual appeal. I must say you have done a excellent job with this. Additionally, the blog loads super fast for me on Firefox. Superb Blog!

  160. Sondra Oswalt says:

    I’d like to thank you for the efforts you’ve put in penning this site. I really hope to check out the same high-grade content by you in the future as well. In fact, your creative writing abilities has encouraged me to get my own blog now ;)

  161. Edra Reidenbach says:

    I’m curious to find out what blog platform you’re working with? I’m having some small security issues with my latest site and I’d like to find something more safeguarded. Do you have any solutions?

  162. Ernesto Behrle says:

    I was very happy to find this internet-site.I wished to thanks to your time for this glorious learn!! I undoubtedly having fun with each little bit of it and I’ve you bookmarked to check out new stuff you weblog post.

  163. Vicki Reisch says:

    I’d like to thank you for the efforts you have put in writing this site. I’m hoping to view the same high-grade blog posts by you later on as well. In fact, your creative writing abilities has encouraged me to get my very own website now ;)

  164. Mitzi Aurges says:

    I’m truly enjoying the design and layout of your website. It’s a very easy on the eyes which makes it much more pleasant for me to come here and visit more often. Did you hire out a developer to create your theme? Superb work!

  165. Jannette Poplawski says:

    Oh my goodness! Awesome article dude! Many thanks, However I am experiencing troubles with your RSS. I don’t understand the reason why I cannot subscribe to it. Is there anybody getting identical RSS problems? Anyone that knows the solution can you kindly respond? Thanx!!

  166. yo says:

    Hello, i think that i noticed you visited my blog so
    i got here to return the choose?.I’m attempting to to find things to enhance my web
    site!I assume its ok to use a few of your concepts!!

  167. Ruben Tonkin says:

    Hi there, I do believe your website could be having web browser compatibility issues. When I take a look at your website in Safari, it looks fine however when opening in I.E., it’s got some overlapping issues. I merely wanted to give you a quick heads up! Other than that, fantastic blog!

  168. Joie says:

    M.E.C Mon Electricien Catalan
    44 Rue Henry de Turenne
    66100 Perpignan
    0651212596

    Electricien Perpignan

    I am really enjoying the theme/design of your weblog. Do you ever run into any web browser
    compatibility problems? A small number of my blog readers have complained about my blog not working
    correctly in Explorer but looks great in Opera.
    Do you have any solutions to help fix this problem?

  169. Lindsey Late says:

    Excellent read, I just passed this onto a friend who was doing some research on that. And he actually bought me lunch because I found it for him smile Thus let me rephrase that: Thanks for lunch!

  170. hey says:

    Taxi moto line
    128 Rue la Boétie
    75008 Paris
    +33 6 51 612 712  

    Taxi moto paris

    Hi there, just wanted to mention, I loved this blog post.
    It was practical. Keep on posting!

  171. Kacey Yoshina says:

    I’ve read some good stuff here. Certainly worth bookmarking for revisiting. I wonder how much effort you put to make such a excellent informative site.

  172. Veronica Minard says:

    I blog quite often and I genuinely appreciate your information. Your article has truly peaked my interest. I am going to take a note of your blog and keep checking for new information about once a week. I subscribed to your RSS feed as well.

  173. 출장 says:

    Thank anyone so much to get letting me personally know what My partner and i didn’t know. I anticipate working with you.

  174. southernlakehome.com says:

    Its like you read my mind! You seem to know
    so much about this, like you wrote the book in it or something.
    I think that you can do with a few pics to drive the message home a bit, but other than that,
    this is excellent blog. An excellent read. I will certainly be back.

  175. Bruno Ochiltree says:

    Howdy! I could have sworn I’ve been to this blog before but after browsing through some of the post I realized it’s new to me. Nonetheless, I’m definitely delighted I found it and I’ll be bookmarking and checking back often!

  176. Gilberto Stalcup says:

    Everything is very open with a very clear description of the challenges. It was truly informative. Your website is extremely helpful. Many thanks for sharing!

  177. Tamica Humenik says:

    You made some first rate factors there. I appeared on the web for the problem and found most people will go along with with your website.

  178. Lolita.tikhonofaOi45 says:

    Perfect update of captcha solution software “XEvil 5.0”:

    Captcha recognition of Google (ReCaptcha-2 and ReCaptcha-3), Facebook, BitFinex, Microsoft, Mail.Ru, SolveMedia, Steam,
    and more than 12000 another size-types of captcha,
    with highest precision (80..100%) and highest speed (100 img per second).
    You can use XEvil 5.0 with any most popular SEO/SMM software: iMacros, XRumer, SERP Parser, GSA SER, RankerX, ZennoPoster, Scrapebox, Senuke, FaucetCollector and more than 100 of other software.

    Interested? You can find a lot of introducing videos about XEvil in YouTube.

    Free XEvil Demo available.

    See you later ;)

    XEvil Net

  179. 용인출장 says:

    Oh my goodness! Impressive article dude! Thank you, However I am going through troubles with your RSS. I donít know the reason why I can’t subscribe to it. Is there anybody getting similar RSS issues? Anybody who knows the answer can you kindly respond? Thanx!!

  180. 구찌 출장 says:

    You’re so awesome! I do not think I’ve truly read anything like that before. So wonderful to discover another person with original thoughts on this topic. Seriously.. thanks for starting this up. This website is something that is required on the internet, someone with a little originality!

  181. Ruthanne Abdel says:

    After I initially left a comment I appear to have clicked on the -Notify me when new comments are added- checkbox and now every time a comment is added I receive 4 emails with the exact same comment. Perhaps there is an easy method you are able to remove me from that service? Cheers!

  182. ดูหนังออนไลน์ 18+ says:

    My spouse and I absolutely love your blog and find nearly all of your post’s to be precisely what I’m looking for. Does one offer guest writers to write content for yourself? I wouldn’t mind writing a post or elaborating on a lot of the subjects you write related to here. Again, awesome site!

  183. what to text the girl your kinda dating says:

    Hello there, simply was alert to your blog through Google, and found that it is really informative. I’m going to watch out for brussels. I’ll appreciate in case you proceed this in future. Many other people will probably be benefited from your writing. Cheers!

  184. Pamela Alphonse says:

    This is a very good tip especially to those fresh to the blogosphere. Brief but very accurate information… Appreciate your sharing this one. A must read post!