Magento2.x 如何建立一個Module?

Magento2.x版本已經發布一段時間了,到如今爲止已經到2.2了,最新版本能夠關注Magento在github上的更新。今天記錄下Magento2.1如何建立一個module,直接進入正題。php

安裝Magento2後,進入項目的根目錄後,進入/app目錄,只有app/design/,app/etc/兩個文件夾,design/目錄是存放主題內容,安裝成功後,在etc/文件夾下會多出config.php和env.php兩個php文件,config.php能夠看到magento2加載了那些模塊,相似magento1.x的eetc/modules/文件夾,env.php保存了鏈接的數據庫的一些信息,若是你要更改項目鏈接的數據庫,能夠在env.php裏面修改,相似Magento1.x的local.xml文件。用過Magento1.x,應該發現app目錄少了code目錄,對頭,這裏咱們也要新建code目錄,用來存放我本身編寫的模塊代碼,首先須要建立一個"<namespace>"(這裏我用Silk),在這個<namespace>下,新建咱們的"<modules>"(這裏我用Test),目錄結構以下所示:html

備註:Magento2.1的全部核心代碼位於/vendor/magento/目錄下。前端

--magento2.1
    |---code
          |---Silk
               |---Test
    |---design
    |---etc
         |---config.php
         |---env.php

建立好咱們的<namespace>和<modules>以後,接下來就須要建立一系列的文件,咱們依次來講每一個文件如何建立。git

模塊聲明

File:app/code/Silk/Test/etc/module.xmlgithub

在module.xml中編寫以下代碼:數據庫

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Silk_Test" setup_version="1.0.0.0" active="true" />
</config>

"module" 標籤說明 :瀏覽器

  • name: 表示module的名稱app

  • setup_version: 表示module的版本號frontend

Module registration

這裏須要在module的根目錄下建立一個"registration.php"文件ide

File:app/code/Silk/Test/registration.php

在registration.php中編寫以下代碼:

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Silk_Test',
    __DIR__
);

查看module是否激活

打開app/etc/config/php文件後,這時你會發現沒有剛纔咱們編寫的module,這裏須要利用終端進入到magento2的根目錄執行magento命令:

php bin/magento setup:upgrade

執行完成以後,你將會在config.php中看到剛纔咱們寫的module。

接下來,咱們就來建立前端控制器。

路由聲明

建立前端控制器時,須要新建etc/frontend/routes.xml文件,來聲明前端控制器的名稱。

File:app/code/Silk/Test/etc/frontend/routes.xml

在routes.php中編寫以下代碼:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="test" frontName="test">
            <module name="Silk_Test" before="Magento_Core"/>
        </route>
    </router>
</config>

<router>標籤說明:

  • id = standard 表示前端路由;

<route>標籤說明:

  • id : 對於router的惟一標識名;

  • frontName : 前端URL的控制名稱;

<router>標籤說明:

  • name : 聲明module的名稱;

  • before : 表示在定義module以前加載;

  • after : 表示在定義moduel以後加載;

備註:「before」 et 「after」 在建立module時不是必須的.

建立前端控制器

好比咱們的URL爲:local.magento2.com/test,繼續建立文件

File:app/code/Silk/Test/Controller/Index/Index.php

控制器中代碼以下:

<?php
namespace Silk\Test\Controller\Index; //這裏使用了php的命名空間
use Magento\Framework\App\Action\Action;
class Index extends Action {
    /** @var  \Magento\Framework\View\Result\Page */
    protected $resultPageFactory;
    /*** @param \Magento\Framework\App\Action\Context $context*/
    public function __construct(\Magento\Framework\App\Action\Context $context,
                                \Magento\Framework\View\Result\PageFactory $resultPageFactory)     {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute()
    {
        echo "this is Silk_Test_Controller_Index_Index";
        die();
    }
}

如今訪問剛纔的路由URL,就能夠看到瀏覽器輸出內容了。

備註:這裏若是報錯:Please upgrade your database: Run "bin/magento setup:upgrade" from the Magento root directory.

解決辦法就是到根目錄執行命令

php bin/magento setup:upgrade

自定義URL

上面咱們的URL很簡單,爲local.magento2.com/test,實際上magento將它轉化成了local.magento2.com/test/index/index,test爲/etc/routes.xml下咱們定義的frontName名,第一個index是位於Controller文件夾下的Index文件夾名,第二個index是位於Index文件夾下的Index.php名,好比咱們如今要咱們的URL爲:local.magento2.com/test/hello/world,咱們該如何建立文件呢?
示例以下:

//File:app/code/Silk/Test/Controller/Helo/World.php
Silk
  |---Test
       |--Controller
            |--Hello
                |---World.php

World.php內容以下:

<?php
namespace Silk\Test\Controller\Hello;
use Magento\Framework\App\Action\Action;

class World extends Action {
    /** @var  \Magento\Framework\View\Result\Page */
    protected $resultPageFactory;
    /*** @param \Magento\Framework\App\Action\Context $context*/
    public function __construct(\Magento\Framework\App\Action\Context $context,
                                \Magento\Framework\View\Result\PageFactory $resultPageFactory)     {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
    public function execute()
    {
        echo "this is Silk_Test_Controller_Hello_World";
        die();
    }
}

建立Block

上面咱們說了如何從控制器輸出內容到頁面,可是真正與瀏覽器頁面最相關的仍是由對應的Block輸出數據,那麼如何建立一個block呢?
咱們來修改下咱們控制器app/code/Silk/Test/Controller/Helo/World.php裏面的內容:

namespace Silk\Test\Controller\Hello;
use Magento\Framework\App\Action\Action;

class World extends Action {
    /** @var  \Magento\Framework\View\Result\Page */
    protected $resultPageFactory;
    /*** @param \Magento\Framework\App\Action\Context $context*/
    public function __construct(\Magento\Framework\App\Action\Context $context,
                                \Magento\Framework\View\Result\PageFactory $resultPageFactory)     {
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * @return \Magento\Framework\View\Result\PageFactory
     */
     public function execute()
     {
        $this->_view->loadLayout();
        $this->_view->getLayout()->initMessages();
        $this->_view->renderLayout();
    }
}

接着建立block文件

File:app/code/Silk/Test/Block/Hello.php

Hello.php中代碼以下:

<?php
namespace Silk\Test\Block;
class Hello extends \Magento\Framework\View\Element\Template
{
    public function _prepareLayout()
    {
        //return parent::_prepareLayout();
    }
}

建立layout佈局文件

佈局文件的命名規則爲:<Router Name>_<Controller Name>_<Action Name>

例如:
local.magento2.com/test -----test_index_index.xml
local.magento2.com/test/say -----test_say_index_index.xml
local.magento2.com/test/hello/world -----test_hello_world.xml

這裏咱們的佈局文件名稱test_hello_world.xml

File:app/code/Silk/Test/view/frontend/layout/test_hello_world.xml

代碼內容以下:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd" layout="2columns-right">
    <body>
        <referenceContainer name="content">
            <block class="Silk\Test\Block\Hello" name="hello" template="helloworld.phtml">
            </block>
        </referenceContainer>
    </body>
</page>

這裏咱們又定義了一個helloworld.phtml文件,繼續來新建這個模板文件。

建立模板文件

File:app/code/Silk/Test/view/frontend/templates/helloworld.phtml

helloworld.phtml代碼內容以下:

<h2>HelloWorld</h2>
<p>Congratulations ! You have created your first Magento Module !</p>
<p>The block classname is : <?php echo get_class($block) ?></p>

如今從新刷新咱們的網頁URL:local.magento2.com/test/hello/world
到此,咱們就完成了一個簡單的前端控制器到模板的數據輸出.須要注意的是,block仍然是提供給模板phtml頁面數據,可是在模板中調用Block中的函數方式時,Magento2是用$block,而再也不是$this.
下面咱們繼續完善咱們這module,在建立後臺部分以前,先來建立Model模型.

建立Model模型

-Model
   |--Job.php
   |--ResourceModel
          |--Job.php
          |--Job
              |--Collection.php

接着咱們依次來建立這幾個文件

File:app/code/Silk/Test/Model/Job.php

代碼內容以下:

<?php
namespace Silk\Test\Model;

use \Magento\Framework\Model\AbstractModel;

class Job extends AbstractModel
{
    const JOB_ID = 'entity_id'; // We define the id fieldname

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

    /**
     * Name of the event object
     *
     * @var string
     */
    protected $_eventObject = 'job';

    /**
     * Name of object id field
     *
     * @var string
     */
    protected $_idFieldName = self::JOB_ID;

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

File:app/code/Silk/Test/Model/ResourceModel/Job.php

代碼內容以下:

<?php
namespace Silk\Test\Model\ResourceModel;

use \Magento\Framework\Model\ResourceModel\Db\AbstractDb;
class Job extends AbstractDb
{
    /**
     * Initialize resource model
     *
     * @return void
     */
    protected function _construct()
    {
        // Table Name and Primary Key column
        $this->_init('silk_job', 'entity_id');
    }

}

File:app/code/Silk/Test/Model/ResourceModel/Job/Collection.php

代碼內容以下:

<?php
namespace Silk\Test\Model\ResourceModel\Job;

use \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;

class Collection extends AbstractCollection
{

    protected $_idFieldName = \Silk\Test\Model\Job::JOB_ID;

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

到此,咱們就建立了一個Model模型.接下來,咱們來建立腳本文件,即Setup/目錄下的文件

  • InstallSchema.php

  • UpgradeSchema.php

  • InstallData.php

  • UpgradeData.php

  • Recurring.php

備註:InstallSchema.php是模塊初次運行時建立表結構的腳本,InstallData.php是模塊初次運行時插入表中的數據,而UpgradeSchema.php和UpgradeData.php是根據module.xml中的setup_version版本號來執行更新表結構和表數據的腳本.

建立表結構InstallSchema.php

File:app/code/Silk/Test/Setup/InstallSchema.php

代碼內容以下:

<?php

namespace Silk\Test\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

/**
 * @codeCoverageIgnore
 */
class InstallSchema implements InstallSchemaInterface
{
    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     */
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;

        $installer->startSetup();

        $table = $installer->getConnection()->newTable(
            $installer->getTable('silk_test')
        )->addColumn(
            'e_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            array('identity' => true, 'nullable' => false, 'primary' => true),
            'Employee ID'
        )->addColumn(
            'e_name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            255,
            array('nullable' => false),
            'Employee Name'
        )->addColumn(
            'e_address',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            '2M',
            array('nullable' => false),
            'Employee Address'
        )->addColumn(
            'is_active',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            array(),
            'Active Status'
        )->addColumn(
            'created_at',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            array(),
            'Creation Time'
        )->addColumn(
            'update_time',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            array(),
            'Modification Time'
        )->setComment(
            'Employee Table'
        );
        $installer->getConnection()->createTable($table);

        $installer->endSetup();

    }
}

upgrade表結構UpgradeSchema.php

File:app/code/Silk/Test/Setup/UpgradeSchema.php

代碼內容以下:

<?php

namespace Silk\Test\Setup;

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


/**
 * @codeCoverageIgnore
 */
class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        if (version_compare($context->getVersion(), '1.0.1') < 0) 
        {
            $installer->startSetup();
            $tableName = $setup->getTable('silk_test');
            if ($setup->getConnection()->isTableExists($tableName) == true) 
            {
                $installer->getConnection()
                ->addColumn($installer->getTable('silk_test'),'e_profile_picture', array(
                    'type'      => Table::TYPE_TEXT,
                    'nullable'  => true,
                    'length'    => 255,
                    'comment'   => 'Profile Picture'
                )); 
            }            
        }
        
        $installer->endSetup();

    }
    
}

備註: 更新表結構要查看module.xml中的schema_version標籤的值是否小於這裏的版本號.

建立後臺配置文件

後臺的配置文件是在etc/adminhtml/目錄下建立,好比menu.xml,routes.xml,system.xml,di.xml等等,依次來解釋下這些xml的做用

menu.xml

menu.xml能夠看做是配置當前模塊在後臺的導航位置的配置信息

File:app/code/Silk/Test/etc/adminhtml/menu.xml

代碼內容以下:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd">
    <menu>
        <add id="Silk_Test::job_head" title="Test" module="Silk_Test" sortOrder="100" parent="Magento_Backend::stores" resource="Silk_Test::job_head" />
        <add id="Silk_Test::job" title="Test" module="Silk_Test" sortOrder="20" parent="Silk_Test::job_head" action="test/job" resource="Silk_Test::job" />
    </menu>
</config>

說明:

  • parent: 'Magento_Backend::stores"表示當前模塊位於後臺Stores選項中;

  • title : 表示在後臺顯示的名稱;

  • id : 惟一標識符;

  • action: 表示點擊該選項要跳轉的路由;

acl.xml

File:app/code/Silk/Test/etc/acl.xml

代碼內容以下:

<?xml version="1.0"?>
<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::content">-->
                <resource id="Silk_Test::job_head" title="Test" sortOrder="100" >
                    <resource id="Silk_Test::department" title="Departments" sortOrder="10">
                        <resource id="Silk_Test::department_save" title="Save Department" sortOrder="10" />
                        <resource id="Silk_Test::department_delete" title="Delete Department" sortOrder="20" />
                    </resource>
                    <resource id="Silk_Test::job" title="Test" sortOrder="20">
                        <resource id="Silk_Test::job_save" title="Save Job" sortOrder="10" />
                        <resource id="Silk_Test::job_delete" title="Delete Job" sortOrder="20" />
                    </resource>
                </resource>
                <!--</resource>-->

                <!-- Admin config -->
                <resource id="Magento_Backend::stores">
                    <resource id="Magento_Backend::stores_settings">
                        <resource id="Magento_Config::config">
                            <resource id="Silk_Test::test" title="Test Section" />
                        </resource>
                    </resource>
                </resource>

            </resource>
        </resources>
    </acl>
</config>

查看權限位置:System > Permissions > User roles;

routes.xml

routes.xml是配置後臺路由的信息

File:app/code/Silk/Test/etc/adminhtml/routes.xml

代碼內容以下:

<?xml version="1.0"?>
<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="Silk_Test" before="Magento_Backend" />
        </route>
    </router>
</config>

說明:

  • frontName: 表示你後臺控制器的名稱

  • id: 惟一標識符;

system.xml

system.xml是配置後臺路由的信息

File:app/code/Silk/Test/etc/adminhtml/system.xml

代碼內容以下:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <tab id="test" translate="label" sortOrder="1000">
            <label>Test</label>
        </tab>
        <section id="test" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Test</label>
            <tab>test</tab>
            <resource>Silk_Test::test</resource>
            <group id="department" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>Test configuration</label>
                <field id="view_list" translate="label comment" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Show job list</label>
                    <comment>Show list of the viewing </comment>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
            </group>
        </section>
    </system>
</config>
相關文章
相關標籤/搜索