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

A Magento jelenleg a világ egyik vezető webáruház motorja, melyet világszerte rengeteg kis- és középvállalkozás mellett megannyi nagy cég is elégedetten használ. Ennek oka a rendkívül gazdag funkcionalitás, mely a gyári funkciók mellett az egyedi, fejlesztői megoldásoknak is köszönhető.

A Magento ugyanis nyílt forráskóddal rendelkező szoftver, ami azt jelenti, hogy szabadon használható, másolható, terjeszthető, tanulmányozható és módosítható. Community edition verziója ráadásul ingyenesen elérhető. Így nem csak bárki szabadon használhatja, de aktív fejlesztői közösség is épül köré. Ilyen módon a rendszerrel kapcsolatos kérdésekre, problémákra bármikor könnyen választ kaphatunk.

Sőt, a jó tanácsok mellett Magento alapú rendszerünk rengeteg különleges modullal, hasznos funkcióval is bővíthető, melyek könnyebbé teszik a munkát és javítják a felhasználói élményt. Ezek a kiegészítők igen széles skálán mozognak és elérhetők a Magento Marketplace piactérről

De annak érdekében, hogy oldalunk tökéletesen működjünk, mi magunk is fejleszthetünk felhasználói modulokat. Ehhez természetesen azonban programozói előképzettség mellett szükségünk lesz bizonyos ismeretekre, melyeket egy többrészes cikksorozatban fogunk részletesen bemutatni.

Ebben a cikkben a következő témákat fogjuk feldolgozni:

  1. Követelmények, dokumentumok és Magento 2.0 installálás
  2. Célszerű IDE beállítások a fejlesztés megkezdése előtt
  3. Alap modul felépítése és elkészítése
  4. Modul admin konfiguráció és jogosultság kezelés
  5. Alap frontend controller, block, layout és template
  6. Modulhoz tartozó adatbázis tábla elkészítése
  7. Modulhoz tartozó adatbázis tábla elkészítése
  8. Modulhoz tartozó modellek és collection létrehozása
  9. Tábla feltöltése adatokkal, script segítségével
  10. Tábla update script és verzió növelés
  11. Adatok megjelenítése frontend-en

1) Követelmények, dokumentumok és Magento 2.0 installálás

A Magento telepítése már önmagában véve olyan feladat, mely igényel némi hozzáértést. Figyelnünk kell arra, hogy minden rendben menjen, különben a munka nagy eséllyel leet hiányos vagy sikertelen. Arra az esetre, ha valami nem a terv szerint történne, érdemes minden fontos adatról biztonsági mentést készítenünk, mielőtt belefognánk a munkába.

Ahhoz, hogy a Magento 2.0 rendszert telepíteni tudjuk, először is kell végeznünk a fejlesztői környezetünk minimális beállításait, mellyel kapcsolatban részletes információt ezzel kapcsolatban ezen a linken olvashatunk: http://devdocs.magento.com/guides/v2.0/install-gde/bk-install-guide.html

Itt az alapvető követelmények jól láthatók, a telepítéshez a következőkre mindenképp szükségünk lesz:

  • PHP 7.1 és ennél nagyobb verziók
  • MySQL 5.6.x és ennél nagyobb verziók
  • Ajánlott legalább 2 GB fizikai memória

Amennyiben nem rendelkezünk ezekkel, a telepítés megkezdése előtt frissíteni kell lokális fejlesztői környezetünket.

A Magento 2.0 rendszer telepítésével kapcsolatban a legfőbb fájlok az alábbi két linken érhetők el: http://devdocs.magento.com/
https://github.com/magento/magento2

Az installálás során három módszert is tudunk alkalmazni.

  1. Az első esetben egyszerűen letöltjük a Magento hivatalos oldalról a két elérhető verziót. Az egyik csak az alap rendszert tartalmazza, míg a másik példa adatokkal is ellátja az installálás során a rendszert (Sample Data). A két csomag itt érhető el: https://www.magentocommerce.com/download
  2. Második telepítési lehetőség, amikor a Github-ról klónozzuk a Magento rendszert. Ennek előnye, hogy folyamatosan frissíteni tudjuk a Git segítségével a fejlesztőkörnyezetünkben. Fontos itt megjegyezni, hogy a Git klónozás során a develop branch-et kapjuk meg, így ahogy a klónozás befejeződött, célszerű átváltani (git checkout) a 2.0 vagy a merchant_beta branch-ekre. A Magento 2.0 Github elérés: https://github.com/magento/magento2
  3. A harmadik lehetőség a Metapackage installáció. Ebben az esetben a letöltött package után a composer segítségével kell installálnunk a Magento 2.0 rendszert, vagyis az alap Magento modulokat a hivatalos Magento Repo-ból kapjuk, az egyéb összetevőket más repo-ból. Metapackage installálási útmutató: magento integrator install

Ha sikerült telepítenünk a keretrendszert, akad néhány beállítás, melyet nem csak érdemes, de szükségszerű is lehet elvégezni. Ezután láthatunk majd neki az első alapmodulunk felépítésének.

2) Célszerű IDE beállítások a fejlesztés megkezdése előtt

Az IDE nem más, mint az integrált fejlesztői környezet (Integrated Development Environment), melynek alapvető szerepe van a gyors alkalmazásfejlesztésben. Az IDE-k általában egy, a a program forráskódjának szerkesztésére alkalmas szövegszerkesztőt, egy fordítóprogramot vagy értelmezőt, fordításautomatizálási eszközöket, valamint nyomkövetési, grafikusfelület-szerkesztési és verziókezelési lehetőségeket is tartalmaznak.

Miután sikeresen installáltuk a Magento 2.0 rendszert fejlesztőkörnyezetünkbe és az megfelelőn működik, célszerű beállítani a fejlesztéshez használt IDE-t, ami e cikk esetében a Jetbrains PhpStorm-ra vonatkozik.

A Magento 2.0 működése és fejlesztése során az alábbi technológiaákat alkalmazza: devdocs magento tech stack.

Első lépésben a projekt megnyitása után a PhpStorm-ban célszerű lefuttatni a Detect PSR-0 Namspace Roots parancsot, ami a menüből elérhető, de egyébként az IDE ezt automatikusan fel fogja ajánlani.

Következő lépés a megfelelő PHP CodeSniffer beállítása. Alapból az IDE a PSR-1 és PSR-2 coding standard-ot támogatja, így itt célszerű a PSR-2-őt választani, de ajánlottabb a PSR-4 alkalmazása (azonban ez alapból nincs a PhpStorm-ban). Az IDE-ben ezen beállítások elvégzésére a cikk nem tér ki. Amennyiben megnyitunk a vendor/magento könyvtárban lévő bármely modulhoz tartozó etc/module.xml fájlt (vagy egyéb itt található xml fájlt), láthatjuk, hogy az URN feloldás jelenleg sikertelen. A Magento 2.0 számos fejlesztői parancsot tartogat számunkra, ami a fejlesztés során segítségünkre lehet. Ezen parancsok listáját így tekintethetjük meg:

  • belépünk a bin könyvtárba a terminálunkban
  • kiadjuk a „php magento” parancsot
  • ennek eredményeképpen kilistázódik az összes lehetséges parancs, amit a fejlesztés során használhatunk és igen hasznos

Visszatérve az URN feloldási problémára, ezt az alábbi paranccsal tudjunk megoldani: php bin/magento dev:urn-catalog:generate .idea/misc.xml (látható, hogy ezt nem a bin könyvtárból futtatjuk, hanem root könyvtárból) A fejlesztés megkezdése előtt kikapcsoljuk a teljes cache-t (admin felületről, vagy fent említett php magento parancsok segítségével). Amennyiben Apache szerver alatt fejlesztünk, a root könyvtárban található .htaccess fájlban beállítjuk a developer módot: SetEnv MAGE_MODE developer Célszerű a fejlesztői környezetünkben az xdebug-ot kikapcsolni (php.ini beállítás), mert ez jelentősen lassítja a rendszert.

3) Alap modul felépítése és elkészítése

Amint installáltuk a Magento 2.0-át (és nem Github-ról klónoztuk), szembesülünk azzal, hogy a jól megszokott app/code könyvtár hiányzik és minden alap Magento modul a vendor/magento könyvtárban van elhelyezve. Ettől nem kell megijedni, a fejlesztés első lépése, hogy létrehozzuk az app/code könyvtárat. Miután ez elkészült, létrehozzuk a modulunk alap könyvtárát (Vendor/Module). Ez a mi esetünkben az Aion/Test könyvtár lesz. Következő lépésben két könyvtárat hozunk létre:

  • app/code/Aion/Test/etc
  • app/code/Aion/Test/Helper

A modul alap definíciós fájlja az app/code/Aion/Test/etc könyvtárba kerül elhelyezésre, melynek neve module.xml.

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 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:Module/etc/module.xsd">
    <module name="Aion_Test" setup_version="2.0.0">
        <sequence>
            <module name="Magento_Store"/>
        </sequence>
    </module>
</config>

A fájlban definiáljuk a modul nevét (Vendor_Module -> Aion_Test), a verzió számát, ami jelen esetben 2.0.0 és a függőségeket, ami jelenleg csak az alap Magento_Store modul. A következő lépésben létrehozzuk a Helper fájlt. Az alap helper fájl az app/code/Aion/Test/Helper/Data.php lesz. Nézzük a tartalmát:

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

/**
 * Aion Test helper
 */
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * Path to store config if extension is enabled
     *
     * @var string
     */
    const XML_PATH_ENABLED = 'aion/basic/enabled';

    /**
     * Check if extension enabled
     *
     * @return string|null
     */
    public function isEnabled()
    {
        return $this->scopeConfig->isSetFlag(
            self::XML_PATH_ENABLED,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
    }
}

A helper fájlt elég üresen is létrehozni, de mi már egy alap függvényt implementáltunk (public function is Enabled()) és egy konstanst. A konstansban meghatározott string (útvonal) később a modulhoz tartozó admin konfigurációs fájlban fog értelmet kapni (system.xml). Következő lépésben elhelyezzük a modul könyvtárba (app/code/Aion/Test) a registration.php fájlt, ami a modul felismerését hivatott elvégezni a Magento 2.0 rendszerben. Nézzük ennek tartalmát:

<?php
/**
 * Copyright © 2015 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */

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

A file tartalmát bármelyik alap Magento 2.0 modulból átmásolhatjuk, a lényeg, hogy a második paraméternél a saját modulunk szerepeljen (Vendor_Modul -> Aion_Test). Mivel az alap Magento 2.0 modulok is composer-t használnak a frissítésre, mi is elkészítjük saját composer.json fájlunkat. Ennek tartalma így néz ki:

{
    "name": "aion/module-test",
    "description": "N/A",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/module-config": "100.0.*",
        "magento/module-store": "100.0.*",
        "magento/module-backend": "100.0.*",
        "magento/framework": "100.0.*"
    },
    "type": "magento2-module",
    "version": "100.0.2",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [
            "registration.php"
        ],
        "psr-4": {
            "Aion\Test\": ""
        }
    }
}

A composer.json tartalmazza modulunk alap információt, függőségeket, licenc, verzió stb. adatokat. Már szinte el is készültünk, de még két fájl hiányzik egy szépen felépített modulhoz.

Ez a két fájl, mely szintén a modulunk könyvtárában (app/code/Aion/Test) kap helyet: README.md és COPYING.txt. Az előbbi a Git leírás, míg az utóbbi a licenc információkat tartalmazza, ami jelen esetben OSL 3.0. Tehát így néz ki a modulunk felépítése: app/code Aion/ Test/ etc/module.xml Helper/Data.php composer.json COPYING.txt README.md registration.php

A következő lépésben aktiválni kell a modult, és megvizsgálni, hogy a Magento 2.0 rendszer felismerte-e megfelelően. A Magento 1.x rendszerben ez a frontend vagy admin oldal frissítéssel történt meg, azonban a 2.0-ban a korábban már említett parancsokat kell alkalmaznunk.

A terminálban belépünk a /bin könyvtárba, majd kiadjuk a php magento module:status parancsot. Ha mindent jól végeztünk el, akkor listázásra kerül az engedélyezett (Enabled) modulok listája és még nem aktív vagy nem engedélyezett (Disabled) modulok listája. Utóbbi helyen jelenik meg a saját modulunk is: Aion_Test. Amennyiben nem jelenik meg, a modulunk felépítése során valamit elrontottunk.

Ezután kiadjuk a terminálban /bin könyvtárban a php magento module:enable Aion_Test parancsot. Ekkor megjelenik, hogy a modult a rendszer felismerte és engedélyezte. Ez valójában azt jelenti, hogy az app/etc/config.php fájlban lévő tömbbe bekerült az ’Aion_Test’ => 1 bejegyzés. Ezután értesítést kapunk, hogy a modult adatbázis szinten is „regisztráljuk” be. Kiadjuk a terminálban a php magento setup:upgrade parancsot.

A parancs végrehajtása során a Magento 2.0 végigfut az összes alap modulon és egyedi modulon és update-eli a rendszert, vagyis lefuttatja a séma és adat scripteket, amennyiben nagyobb verzió számot talál, mint a jelenlegi. Mindez a mi modulunk esetében az jelenti, hogy korábban leírt 2.0.0 verzió szám beírásra kerül a setup_module táblába.

Ha ezután belépünk az admin felületre és kiválasztjuk Store / Configuration menüpontot, majd ezt követően az Advanced / Advanced aloldalt, akkor megjelenik a modulunk a listában enabled állapotban. Ezzel el is készültünk az alap modulunkkal.

4) Modul admin konfiguráció és jogosultság kezelés

Miután az alap modulunk elkészült, felépítjük a hozzá tartozó admin konfigurációt és jogosultság kezelést. Első lépésben a konfigurációhoz szükséges fájlt hozzuk létre, ami az app/code/Aion/Test/etc/adminhtml könyvtárban lesz elhelyezve és a neve system.xml.

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 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_Config:etc/system_file.xsd">
    <system>
        <tab id="aion_tab" translate="label" sortOrder="500">
            <label>Aion Extensions</label>
        </tab>
        <section id="aion" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Test Extension</label>
            <tab>aion_tab</tab>
            <resource>Aion_Test::test</resource>
            <group id="basic" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Basic</label>
                <field id="enabled" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Enable Extension</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
            </group>
            <group id="more" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>More</label>
                <field id="variable" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Some Variable</label>
                </field>
            </group>
        </section>
    </system>
</config>

A fájlban definiálunk egy <tab> tag-et is, így a modulunk saját menüpontban (Aion Extensions -> Test Extension) fog megjelenni az admin Stores / Configuration aloldalán. Ezen belül implementálunk két tab-ot (basic és more id-kkal). Az elsőbe helyezzük el az alap No / Yes select típusú konfigurációs változót, amit a modul engedélyezésére és tiltására használunk. Lekérdezését már korábban implementáltuk a Data.php file-ban(Helper/Data.php). A példa kedvéért létrehozunk egy text típusú konfigurációs változót is Variable névvel későbbi használatra.

A fájlban még fontos rész a <resource> tag is, aminek a jogosultság kezelés implementálásakor lesz szerepe. Ez a mi esetünkben Aion_Test::test.   A következő lépésben létrehozzuk a jogosultság kezeléshez szükséges fájlt is, ami az app/code/Aion/Test/etc könyvtárba kerül acl.xml néven. Ennek tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 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:Acl/etc/acl.xsd">
    <acl>
        <resources>
            <resource id="Magento_Backend::admin">
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="Aion_Test::test" title="Aion Test Extension Section" />
                        </resource>
                    </resource>
                </resource>
            </resource>
        </resources>
    </acl>
</config>

Amint ezzel készen vagyunk, leellenőrizzük, hogy megfelelően létrejött-e a modulhoz tartozó jogosultság beállítás a Role Resource (Admin felhasználó szerepek) részben. Az admin felületen megnyitjuk a System / User Roles menüpontot, majd itt bármelyik adminisztrátori csoportot (alapból egy van) megnyitva a Role Resouces almenüt kiválasztva, majd a Resource Access-nél a Custom lehetőség alatt megvizsgáljuk, hogy a fában megjelenik-e a saját modulunk.

Ezt követően leellenőrizzük a korábban kialakított konfigurációs menüpont, és hogy tartalma is megjelenik-e. Az adminban a Stores / Configuration-t választva a bal menüben megnézzük, hogy megjelent-e a saját menüpontunk (Aion Extensions) és annak taralma (Test Extension). Az alap konfigurációs értékeket az app/code/Aion/Test/etc könyvtárban lévő config.xml fájlban határozzuk meg:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 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_Store:etc/config.xsd">
    <default>
        <aion>
            <basic>
                <enabled>1</enabled> 
            </basic>
        </aion>
    </default>
</config>

Jól látható, hogy a file-ban látható tag-ek megfelelnek a system.xml-ben lévő saját id-kkal.

5) Alap frontend controller, block, layout és template

A következőkben létrehozunk egy saját frontend controller-t, a hozzátartozó layout és router konfigurációt. Majd ezt követően egy template fájlt és a hozzá tartozó block-ot is implementáljuk. Elsőként elkészítjük a controller fájlt, ami valójában egy Action-t jelent. Ezt az app/code/Aion/Test/Controller/Index/ könyvtárban lévő Index.php-val implementáljuk. A fájl tartalma:

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

use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Controller\Result\ForwardFactory;
use Magento\Framework\Exception\NotFoundException;
use Magento\Framework\App\RequestInterface;

/**
 * Contact index controller
 */
class Index extends \Magento\Framework\App\Action\Action
{
    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @var ForwardFactory
     */
    protected $resultForwardFactory;

    /**
     * @var \Aion\Test\Helper\Data
     */
    protected $helper;

    /**
     * Index constructor.
     *
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
     * @param \Aion\Test\Helper\Data $helper
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        ForwardFactory $resultForwardFactory,
        \Aion\Test\Helper\Data $helper
    ) {
        $this->resultPageFactory = $resultPageFactory;
        $this->resultForwardFactory = $resultForwardFactory;
        $this->helper = $helper;
        parent::__construct($context);
    }

    /**
     * Dispatch request
     *
     * @param RequestInterface $request
     * @return \Magento\Framework\App\ResponseInterface
     * @throws \Magento\Framework\Exception\NotFoundException
     */
    public function dispatch(RequestInterface $request)
    {
        if (!$this->helper->isEnabled()) {
            throw new NotFoundException(__('Page not found.'));
        }
        return parent::dispatch($request);
    }

    /**
     * Aion Test Page
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        /** @var \Magento\Framework\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set(__('Aion Test Page'));
        if (!$resultPage) {
            $resultForward = $this->resultForwardFactory->create();
            return $resultForward->forward('noroute');
        }
        return $resultPage;
    }
} 

A fájlban három fontos függvény található, mindhárom a szülőosztályban van definiálva. A __construct függvényt használjuk arra, hogy az általunk használni kívánt egyéb osztályokat injektáljuk (pl. helper osztály, dependency injection).  A dispatch függvény automatikusan le fog futni a __construct után. Itt vizsgáljuk meg, hogy a modulunk engedélyezve van-e, vagy sem és megfelelően lekezeljük. Végül pedig az execute függvény jelenti magát az action-t, ami a jelenlegi esetben az Index action-nek felel meg.

A működése során a $resultPageFactory objektumot létrehozzuk (ami a későbbi layout konfiguráció alapján felépíti az oldalt). Az objektum setConfig függvényével beállítunk egy oldal title-t. Ezután megvizsgáljuk, hogy az objektum létrejött-e, vagy sem. Amennyiben nincs hiba, visszatérünk a $resultPage objektummal, ellenkező esetben noroute (vagyis 404-es) oldalra irányítjuk az action-t.   Létrehozzuk az app/code/Aion/Test/etc/frontend könyvtárban a routes.xml fájlt, amiben meghatározzuk, hogy milyen url alatt szeretnénk meghívni a modulunkhoz controller-eket. A fájl tartalma:

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

use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Controller\Result\ForwardFactory;
use Magento\Framework\Exception\NotFoundException;
use Magento\Framework\App\RequestInterface;

/**
 * Contact index controller
 */
class Index extends \Magento\Framework\App\Action\Action
{
    /**
     * @var PageFactory
     */
    protected $resultPageFactory;

    /**
     * @var ForwardFactory
     */
    protected $resultForwardFactory;

    /**
     * @var \Aion\Test\Helper\Data
     */
    protected $helper;

    /**
     * Index constructor.
     *
     * @param \Magento\Framework\App\Action\Context $context
     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
     * @param \Magento\Framework\Controller\Result\ForwardFactory $resultForwardFactory
     * @param \Aion\Test\Helper\Data $helper
     */
    public function __construct(
        Context $context,
        PageFactory $resultPageFactory,
        ForwardFactory $resultForwardFactory,
        \Aion\Test\Helper\Data $helper
    ) {
        $this->resultPageFactory = $resultPageFactory;
        $this->resultForwardFactory = $resultForwardFactory;
        $this->helper = $helper;
        parent::__construct($context);
    }

    /**
     * Dispatch request
     *
     * @param RequestInterface $request
     * @return \Magento\Framework\App\ResponseInterface
     * @throws \Magento\Framework\Exception\NotFoundException
     */
    public function dispatch(RequestInterface $request)
    {
        if (!$this->helper->isEnabled()) {
            throw new NotFoundException(__('Page not found.'));
        }
        return parent::dispatch($request);
    }

    /**
     * Aion Test Page
     *
     * @return \Magento\Framework\View\Result\Page
     */
    public function execute()
    {
        /** @var \Magento\Framework\View\Result\Page $resultPage */
        $resultPage = $this->resultPageFactory->create();
        $resultPage->getConfig()->getTitle()->set(__('Aion Test Page'));
        if (!$resultPage) {
            $resultForward = $this->resultForwardFactory->create();
            return $resultForward->forward('noroute');
        }
        return $resultPage;
    }
} 

A router konfigurációban látható, hogy a modulunkhoz a „test” url-t rendeltük, vagyis ez esetben a {{base_url}}test/index/index fogja meghívni a fent részletezett controller-t és azon belül az execute függvényt (Index action). Természetesen index controllert és action-t nem kell megadni mindig az url-ben, a {{base_url}}test/ is ugyanerre a helyre fog minket irányítani.   Következőkben létrehozzuk a layout fájlt ami az app/code/Aion/Test/view/frontend/layout könyvtárban kap helyet test_index_index.xml néven. Jól látható, hogy a fájl neve követi a router -> controller -> action neveket. A fájl tartalma:

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <title>Aion Test Page</title>
    </head>
    <body>
        <referenceContainer name="content">
            <block class="Aion\Test\Block\Test" name="testPage" template="Aion_Test::test.phtml" />
        </referenceContainer>
    </body>
</page>

A layout file <head> részében beállítjuk az oldal alap címét, a tartalmi részben (content) egy block-ot és a hozzá tartozó template fájlt is definiáljuk. A block-ot az app/code/Aion/Test/Block könyvtárban lévő Test.php-ban valósítjuk meg. A fájl tartalma:

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

use Magento\Framework\View\Element\Template;

/**
 * Aion Test Page block
 */
class Test extends Template
{
    /**
     * @param Template\Context $context
     * @param array $data
     */
    public function __construct(Template\Context $context, array $data = [])
    {
        parent::__construct($context, $data);
    }

    /**
     * Test function
     *
     * @return string
     */
    public function getTest()
    {
        return 'This is a test function for some logic...';
    }
}  

Észrevehetjük, hogy a példában használt __construct függvényben nem deklaráltunk semmit, így ez lényegében el is hagyható. Azonban célszerű már az elején megvalósítani, ha például később egy storeManager vagy Helper-t vagy bármi mást is szeretnénk implementálni. A template file az app/code/Aion/Test/view/frontend/templates könyvtárban kap helyet test.phtml néven. A fájl tartalma:

<?php
/**
 * Copyright © 2015 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
?>

<?php
/**
 * @var $block \Aion\Test\Block\Test
 */
?>

<p><?php echo $block->getTest(); ?></p>
<p><?php echo __('This is a text.') ?></p>

A template file a példa kedvéért meghívja a Block-ban definiált teszt függvényt, és emellett egy egyszerű string-et is kiír, ami egy translate függvénybe van ágyazva. Ha mindennel elkészültünk, a modulunk így néz ki: app/code Aion/ Test/ Block/Test.php Controller/Index/Index.php etc/adminhtml/system.xml /frontend/routes.xml acl.xml config.xml module.xml Helper/Data.php view/frontend /layout/test_index_index.xml /templates/test.phtml composer.json COPYING.txt README.md registration.php

Az előzőekben megismerkedtünk egy alap Magento 2.0 modul elkészítésével és felépítésével. Most folytatjuk, és megismerkedünk azzal, hogyan készíthetünk saját adatbázis táblát, tölthetjük fel alapadatokkal a modulunkhoz, és a táblaadatok kezeléséhez szükséges modellekkel, ill. collection-nel. Emellett a frontend-en megnézzük, hogy érhetőek el tábla adatok és milyen módon jeleníthetjük meg őket.

6) Modulhoz tartozó adatbázis tábla elkészítése – 1

A modulhoz tartozó adatbázis táblát egy a Magento 1.x-ből már ismert installer script segítségével készíthetjük el, azonban a file neve és felépítése kicsit eltérő.   Az adatbázis táblát az app/code/Aion/Test/Setup könyvtárban lévő InstallSchema.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\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Adapter\AdapterInterface;

/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * Install table
     *
     * @param \Magento\Framework\Setup\SchemaSetupInterface $setup
     * @param \Magento\Framework\Setup\ModuleContextInterface $context
     * @throws \Zend_Db_Exception
     */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();
        /**
         * Create table 'aion_test'
         */
        $table = $installer->getConnection()->newTable(
            $installer->getTable('aion_test')
        )->addColumn(
            'test_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['identity' => true, 'nullable' => false, 'primary' => true],
            'Test ID'
        )->addColumn(
            'name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Test Name'
        )->addColumn(
            'email',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            ['nullable' => false],
            'Test Email'
        )->addColumn(
            'creation_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
            'Test Creation Time'
        )->addColumn(
            'update_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
            'Test Modification Time'
        )->addColumn(
            'is_active',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['nullable' => false, 'default' => '1'],
            'Is Test Active'
        )->addIndex(
            $setup->getIdxName(
                $installer->getTable('aion_test'),
                ['name', 'email'],
                AdapterInterface::INDEX_TYPE_FULLTEXT
            ),
            ['name', 'email'],
            ['type' => AdapterInterface::INDEX_TYPE_FULLTEXT]
        )->setComment(
            'Aion Test Table'
        );
        $installer->getConnection()->createTable($table);

        $installer->endSetup();
    }
}

A script létrehozza a modulhoz tartozó példa táblát, aminek neve „aion_test” lesz. Ezután létrehozza az alábbi mezőket is:

  • test_id – primary key, smallint (6)
  • name – varchar (255)
  • email – varchar (255)
  • creation_time – timestamp
  • update_time – timestamp
  • is_active – smallint (6)

Ezt követően a scriptben célszerű és erősen ajánlott index-szel (addIndex) ellátni azon text (text és varchar és egyéb, ha szükséges) típusú oszlopokat, melyekben keresni fogunk a későbbiekben vagy a leendő collection-t szűrni fogjuk. A példa esetében ez a két mező a name és az email.

7) Modulhoz tartozó adatbázis tábla elkészítése – 2

Korábban már adtunk verziószámot a modulunkhoz az app/code/Aion/Test/etc könyvtárban lévő module.xml segítségével ‒ amiben meghatároztuk az alap verziót, majd a modul engedélyezése (terminál parancsok) segítségével ez a verziószám bekerült a „setup_module” Magento 2.0 táblába. Arra, hogy fent elkészített script lefusson, két lehetőségünk van: növeljük a verziószámot a modulunkban, vagy töröljük a modulunkhoz tartozó korábbi verziószám bejegyzést.

Mivel még csak a modul fejlesztésének elején tartunk, így célszerű törölni „setup_module” Magento 2.0 táblából a modulunkhoz tartozó bejegyzést. Miután ezt megtettük, ismét futtassuk le a setup:upgrade magento parancsot a terminálból. Ha mindent jól csináltunk, a modulhoz tartozó táblánk létrejön az adatbázisban.

8) Modulhoz tartozó modellek és collection létrehozása

Ahhoz, hogy adatokkal tudjuk feltölteni az elkészült táblát vagy adatokat tudjunk lekérdezni, el kell készítenünk a modul model, resource és collection file-okat. Az alap model file az app/code/Aion/Test/Model 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\Model;

/**
 * Aion Test model
 *
 * @method \Aion\Test\Model\ResourceModel\Test _getResource()
 * @method \Aion\Test\Model\ResourceModel\Test getResource()
 * @method string getId()
 * @method string getName()
 * @method string getEmail()
 * @method setSortOrder()
 * @method int getSortOrder()
 */
class Test extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Statuses
     */
    const STATUS_ENABLED = 1;
    const STATUS_DISABLED = 0;

    /**
     * Aion Test cache tag
     */
    const CACHE_TAG = 'aion_test';

    /**
     * @var string
     */
    protected $_cacheTag = 'aion_test';

    /**
     * Prefix of model events names
     *
     * @var string
     */
    protected $_eventPrefix = 'aion_test';

    /**
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Aion\Test\Model\ResourceModel\Test');
    }

    /**
     * Get identities
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId(), self::CACHE_TAG . '_' . $this->getId()];
    }

    /**
     * Prepare item's statuses
     *
     * @return array
     */
    public function getAvailableStatuses()
    {
        return [self::STATUS_ENABLED => __('Enabled'), self::STATUS_DISABLED => __('Disabled')];
    }

}

A model file-ban definiáljuk a Magento 2.0 cache működéshez szükséges két cache tag-et. Fontos még event prefix-et is definiálni, hogy később observer-ek használata esetén tudjuk használni, mint event name. A legfontosabb a _construct() függvény, melyben meghatározzuk a modellhez tartozó resource modellt. A getAvailableStatuses() függvényt és két STATUS_* konstansokat későbbi használatra célszerű létrehozni. A getIdentities() függvény implementálása nem kötelező, de a cache kezelés megfelelő működéséhez célszerű.

Miután elkészült az alap modell fájlunk, hozzuk létre a hozzá tartozó resource modellt is. Az alap resource modell fájlt az app/code/Aion/Test/Model/ResourceModel 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\Model;

/**
 * Aion Test model
 *
 * @method \Aion\Test\Model\ResourceModel\Test _getResource()
 * @method \Aion\Test\Model\ResourceModel\Test getResource()
 * @method string getId()
 * @method string getName()
 * @method string getEmail()
 * @method setSortOrder()
 * @method int getSortOrder()
 */
class Test extends \Magento\Framework\Model\AbstractModel
{
    /**
     * Statuses
     */
    const STATUS_ENABLED = 1;
    const STATUS_DISABLED = 0;

    /**
     * Aion Test cache tag
     */
    const CACHE_TAG = 'aion_test';

    /**
     * @var string
     */
    protected $_cacheTag = 'aion_test';

    /**
     * Prefix of model events names
     *
     * @var string
     */
    protected $_eventPrefix = 'aion_test';

    /**
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Aion\Test\Model\ResourceModel\Test');
    }

    /**
     * Get identities
     *
     * @return array
     */
    public function getIdentities()
    {
        return [self::CACHE_TAG . '_' . $this->getId(), self::CACHE_TAG . '_' . $this->getId()];
    }

    /**
     * Prepare item's statuses
     *
     * @return array
     */
    public function getAvailableStatuses()
    {
        return [self::STATUS_ENABLED => __('Enabled'), self::STATUS_DISABLED => __('Disabled')];
    }

}

A legfontosabb, amit implementálnunk kell, a protected _construct() függvény, amiben meghatározzuk, hogy a korábban létrehozott táblához melyik mező a primary key. Miután elkészültünk a resource modellel, készítsük el a collection-t is. Az alap collection osztály fájlt az app/code/Aion/Test/Model/ResourceModel/Test 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;

/**
 * Aion Test collection
 */
class Collection extends \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
{
    /**
     * @var string
     */
    protected $_idFieldName = 'test_id';

    /**
     * Store manager
     *
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $storeManager;

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

    /**
     * Define resource model
     *
     * @return void
     */
    protected function _construct()
    {
        $this->_init('Aion\Test\Model\Test', 'Aion\Test\Model\ResourceModel\Test');
    }
}

A collection osztályban a _construct() függvényt implementáljuk, ahol valójában meghatározzuk, hogy a korábban elkészített modell osztályhoz melyik resource modell osztály tartozik. Lényegében ez elég is lenne collection-nek, azonban előretekintve helyezzük be (injektáljuk) már most a store manager osztályt is a public __construct() függvénybe későbbi felhasználás végett, hiszen minden modulnál követelmény a multistore támogatás. Amennyiben a három fájllal elkészültünk, akkor már létre is hoztuk azon osztályokat, melyekkel adatokat tudunk írni, ill. olvasni korábban létrehozott adatbázis táblánkból.

9) Tábla feltöltése adatokkal, script segítségével

A modell struktúra elkészítése szükséges volt ahhoz, hogy script-tel is tudjunk adatokat hozzáadni a modul alap táblájához. Az adat script-et az app/code/Aion/Test/Setup könyvtárban lévő InstallData.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\Setup;

use Aion\Test\Model\Test;
use Aion\Test\Model\TestFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * Test factory
     *
     * @var TestFactory
     */
    private $testFactory;

    /**
     * Init
     *
     * @param TestFactory $testFactory
     */
    public function __construct(TestFactory $testFactory)
    {
        $this->testFactory = $testFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $testItems = [
            [
                'name' => 'John Doe',
                'email' => 'john.doe@example.com',
                'is_active' => 1,
            ],
            [
                'name' => 'Jane Doe',
                'email' => 'jane.doe@example.com',
                'is_active' => 0,
            ],

            [
                'name' => 'Steve Test',
                'email' => 'steve.test@example.com',
                'is_active' => 1,
            ],
        ];

        /**
         * Insert default items
         */
        foreach ($testItems as $data) {
            $this->createTest()->setData($data)->save();
        }

        $setup->endSetup();
    }

    /**
     * Create Test item
     *
     * @return Test
     */
    public function createTest()
    {
        return $this->testFactory->create();
    }
}

Az InstallData osztályban implementáljuk az install(…) függvényt, melyben létrehozzuk a teszt adatokat egy többdimenziós tömbben. Majd ezen végig iterálva meghívjuk a createTest() függvényt, melynek az új Test modell létrehozása a feladata, és a tömbök, mint adatok hozzáadása után mentjük a modellt.

Itt fontos megemlíteni az osztályban létrehozott és __construct() függvényben injektált TestFactory osztályt is. Ezt az osztályt a Magento 2.0 hozza létre automatikusan a /var/generation/Aion/Test/Model könyvtárba az első futása során ($this->testFactory-> create()). Mivel még mindig a modulunk fejlesztése elején tartunk, dobjuk el manuálisan a korábban létrehozott „aion_test” táblát az adatbázisból, és töröljük a „setup_module” Magento 2.0 táblából a modulunkhoz tartozó bejegyzést. Miután ezt megtettük, ismét futtassuk le a setup:upgrade magento parancsot terminálból.

Ha mindent jól csináltunk, a modulhoz tartozó táblánk ismét létrejön az adatbázisban immár adatokkal feltöltve. Természetesen ehelyett verziószám módosítással (emeléssel) is tudjuk az adatfeltöltést futtatni parancssorból, így ekkor nem kell manuálisan eldobni a korábban létrehozott táblánkat és „setup_module” táblába sem kell belenyúlni.

10) Tábla update script és verzió növelés

Ahogy fejlesztjük a modulunkat, sokszor lesz szükségünk az alap adatbázis tábla módosítására, esetleg új adatbázis tábla létrehozására. A Magento 1.x-ben ezt upgrade script-ekkel tehettük meg, mint adatbázis, mint pedig data oldalon. A Magento 2.0 modulunk sincs másképp, csak szerencsére az adatbázis script-eket egy fájlban kell ezúton kezelni, több különálló fájl helyett.

Az adatbázis update script-et az app/code/Aion/Test/Setup könyvtárban lévő UpgradeSchema.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\Setup;

use Aion\Test\Model\Test;
use Aion\Test\Model\TestFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * Test factory
     *
     * @var TestFactory
     */
    private $testFactory;

    /**
     * Init
     *
     * @param TestFactory $testFactory
     */
    public function __construct(TestFactory $testFactory)
    {
        $this->testFactory = $testFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $testItems = [
            [
                'name' => 'John Doe',
                'email' => 'john.doe@example.com',
                'is_active' => 1,
            ],
            [
                'name' => 'Jane Doe',
                'email' => 'jane.doe@example.com',
                'is_active' => 0,
            ],

            [
                'name' => 'Steve Test',
                'email' => 'steve.test@example.com',
                'is_active' => 1,
            ],
        ];

        /**
         * Insert default items
         */
        foreach ($testItems as $data) {
            $this->createTest()->setData($data)->save();
        }

        $setup->endSetup();
    }

    /**
     * Create Test item
     *
     * @return Test
     */
    public function createTest()
    {
        return $this->testFactory->create();
    }
}

A példában egy új mezőt (sort_order) adunk az alap adatbázis táblához („aion_test”) upgrade script segítségével. Az upgrade függvényben implementált módosítás csak akkor fog lefutni, ha a modul verziószáma eléri a példában látható 2.0.1 értéket.

11) Adatok megjelenítése frontend-en

Ahhoz, hogy frontend-en a létrehozott adatokat meg tudjuk jeleníteni, módosítani kell a frontend template-et és a hozzá tartozó block osztályt is. Az block osztályt már korábban elkészítettük, most kiegészítjük. A block osztály az  app/code/Aion/Block/ 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\Setup;

use Aion\Test\Model\Test;
use Aion\Test\Model\TestFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallData implements InstallDataInterface
{
    /**
     * Test factory
     *
     * @var TestFactory
     */
    private $testFactory;

    /**
     * Init
     *
     * @param TestFactory $testFactory
     */
    public function __construct(TestFactory $testFactory)
    {
        $this->testFactory = $testFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $testItems = [
            [
                'name' => 'John Doe',
                'email' => 'john.doe@example.com',
                'is_active' => 1,
            ],
            [
                'name' => 'Jane Doe',
                'email' => 'jane.doe@example.com',
                'is_active' => 0,
            ],

            [
                'name' => 'Steve Test',
                'email' => 'steve.test@example.com',
                'is_active' => 1,
            ],
        ];

        /**
         * Insert default items
         */
        foreach ($testItems as $data) {
            $this->createTest()->setData($data)->save();
        }

        $setup->endSetup();
    }

    /**
     * Create Test item
     *
     * @return Test
     */
    public function createTest()
    {
        return $this->testFactory->create();
    }
}

A block osztály konstruktorába implementáljuk a korábban létrehozott Test modelt és a hozzá tartozó testFactory-t és ezek mellett a collectionFactory-t (itemCollectionFactory) is. A collectionFactory osztály nagyon hasonló a testFactory-hoz, szintén a Magento 2.0 hozza létre a var/generation/Aion/Test/Model/ResourceModel/Test/ könyvtárban az első meghívása után. A getTestModel() függvény egy modellt példányosít, és a betöltésért felelős, míg a getItems() függvény egy teljes collection-t hoz létre.

A block-hoz tartozó template file-ban kiírathatjuk az adatokat tesztelésképp. A fájl tartalma:

<?php
/**
 * Copyright © 2016 AionNext Ltd. All rights reserved.
 * See COPYING.txt for license details.
 */
?>

<?php
/**
 * @var $block \Aion\Test\Block\Test
 */
?>
<div class="aion-test">
    <h2><?php echo __('This is a test extension!') ?></h2>
    <!-- See a sample model -->
    <?php \Zend_Debug::dump($block->getTestModel()->getData()); ?>
    <!-- See a sample collection -->
    <?php \Zend_Debug::dump($block->getItems()->getData()); ?>

    <!-- See a sample collection iteration -->
    <?php $items = $block->getItems(); ?>
    <?php if ($items->getSize()) : ?>
        <?php foreach ($items as $item) : ?>
            <h3><?php echo $block->stripTags($item->getName()) ?></h3>
            <p>
                <span><?php echo __('Email:'); ?></span>&nbsp;
                <span><?php echo $item->getEmail() ?></span>
            </p>
        <?php endforeach; ?>
    <?php endif; ?>
</div>

Ebben a cikkben részletesen átvettünk jó néhány témakört az alap Magento 2.0 modulunk fejlesztéséhez: hozzáadtunk egy saját adatbázis táblát, és teszt adatokkal feltöltöttük. Az ehhez szükséges modellt, resource-t és collection-t is létrehoztuk, ill. a teszt adatokat megjelenítettük a frontend-en is.

VÉGE AZ 1. RÉSZNEK, DE HAMAROSAN FOLYTATJUK!   A 2. részben  a modulhoz tartozó admin táblázat (grid) elkészítésével, illetve a szükséges controllerek-kel is megismerkedünk majd.