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.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__ );
打開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很簡單,爲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呢?
咱們來修改下咱們控制器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(); } }
佈局文件的命名規則爲:<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 |--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版本號來執行更新表結構和表數據的腳本.
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(); } }
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能夠看做是配置當前模塊在後臺的導航位置的配置信息
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: 表示點擊該選項要跳轉的路由;
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是配置後臺路由的信息
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是配置後臺路由的信息
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>