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>