9.如何创建安装、升级、卸载脚本
本文主要研究一下Magento2 模块中如何使用安装升级的SQL脚本。在你安装或升级一个模块时,你或许想要修改数据表结构或新增一些数据,Magento 2为这些需求提供了一些类。
本节目录:
- InstallSchema / InstallData
- UpgradeSchema / UpgradeData
- 更新数据表或数据
- 更新数据表
- 更新数据
- 循环
- 卸载
安装、更新、卸载 SQL 脚本简介
- InstallSchema 这个类在模块安装时运行创建数据表结构
- InstallData 这个类在模块安装时运行初始化数据表的数据
- UpgradeSchema 这个类在模块更新时运行修改数据表结构
- UpgradeData 这个类在模块更新时运行从数据表添加或删除数据
- Recurring 循环
- Uninstall 卸载
以上所有类都在文件夹: app/code/Vendor/Module/Setup
。 在每次运行以下命令时安装或更新脚本会运行:
php bin/magento setup:upgrade
本章节继续使用前面的 HelloWorld 模块。
安装脚本: InstallSchema & InstallData
InstallSchema 和 InstallData 这两个类会在模块安装时运行
InstallSchema会修改数据表结构。如下代码创建 aqrun_helloworld_post 数据表:
文件: app/code/Aqrun/HelloWorld/Setup/InstallSchema.php
<?php
namespace Aqrun\HelloWorld\Setup;
use \Magento\Framework\DB\Ddl\Table;
class InstallSchema implements \Magento\Framework\Setup\InstallSchemaInterface
{
public function install(
\Magento\Framework\Setup\SchemaSetupInterface $setup,
\Magento\Framework\Setup\ModuleContextInterface $context
){
$installer = $setup;
$installer->startSetup();
if (!$installer->tableExists('aqrun_helloworld_post')) {
$table = $installer->getConnection()->newTable(
$installer->getTable('aqrun_helloworld_post')
)->addColumn(
'post_id',
Table::TYPE_INTEGER,
null,
[
'identity' => true,
'nullable' => false,
'primary' => true,
'unsigned' => true,
],
'Post ID'
)->addColumn(
'name',
Table::TYPE_TEXT,
255,
['nullable' => false],
'Post name'
)->addColumn(
'url_key',
Table::TYPE_TEXT,
255,
['nullable' => false],
'Post URL Key'
)->addColumn(
'post_content',
Table::TYPE_TEXT,
'64k',
[],
'Post Content'
)->addColumn(
'tags',
Table::TYPE_TEXT,
255,
[],
'Post Tags'
)->addColumn(
'status',
Table::TYPE_INTEGER,
1,
[],
'Post Status'
)->addColumn(
'featured_image',
Table::TYPE_TEXT,
255,
[],
'Post Featured Image'
)->addColumn(
'created_at',
Table::TYPE_TIMESTAMP,
null,
['nullable' => false, 'default' => Table::TIMESTAMP_INIT],
'Created At'
)->addColumn(
'updated_at',
Table::TYPE_TIMESTAMP,
null,
['nullable' => false, 'default' => Table::TIMESTAMP_INIT_UPDATE],
'Updated At'
)->setComment('Post Table');
$installer->getConnection()->createTable($table);
$installer->getConnection()->addIndex(
$installer->getTable('aqrun_helloworld_post'),
$setup->getIdxName(
$installer->getTable('mageplaza_helloworld_post'),
['name', 'url_key', 'post_content', 'tags', 'featured_image'],
\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
),
['name','url_key','post_content','tags','featured_image',],
\Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
);
}//if
$installer->endSetup();
}
}
代码解释:
这个类必须实现接口: \Magento\Framework\Setup\InstallSchemaInterface
这个类必须实现 install()
方法,并且有两个参数 SchemaSetupInterface
和 ModuleContextInterface
。SchemaSetupInterface
接口类型的 setup
对象提供了很多和数据库服务器进行交互的函数。ModuleContextInterface
只有一个方法 getVersion()
用来获取模块的当前版本号。
上面代码中我们创建了名为 aqrun_helloworld_post
的数据表,字段有: post_id, name, post_content,created_at 等。
InstallSchema
运行完成后,会执行 InstallData
类给数据表添加数据
文件: app/code/Aqrun/HelloWorld/Setup/InstallData.php
<?php
namespace Aqrun\HelloWorld\Setup;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface
{
protected $_postFactory;
public function __contruct(
\Aqrun\HelloWorld\Model\PostFactory $postFactory
){
$this->_postFactory = $postFactory;
}
public function install(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
){
$data = [
'name' => '测试文章标题',
'post_content' => '测试正文内容好多内容',
'url_key' => '/module-test/test-post-title.html',
'tags' => '测试,内容,标题',
'status' => 1
];
$post = $this->_postFactory->create();
$post->addData($data)->save();
}
}
这个类和 InstallSchema
类的结构意义相同
更新脚本: UpgradeSchema & UpgradeData
这两个文件会在模块安装后或更新后都运行。这两个类和安装脚本类不同,它们在模块每次更新时都会运行。所以我们需要对比版本号并且按版本号把脚本分开,版本号指的是 app/code/Aqrun/HelloWorld/etc/module.xml
文件的 setup_version
属性值
本例中我们修改 setup_version 为 1.2.0
文件: app/code/Aqrun/HelloWorld/etc/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="Aqrun_HelloWorld" setup_version="1.2.0">
</module>
</config>
更新脚本
文件: app/code/Aqrun/HelloWorld/Setup/UpgradeSchema.php
<?php
namespace Aqrun\HelloWorld\Setup;
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Famework\Setup\ModuleContextInterface;
class UpgradeSchema implements UpgradeSchemaInterface
{
public function upgrade(
SchemaSetupInterface $setup,
ModuleContextInterface $context
){
$installer = $setup;
$installer->startSetup();
if(version_compare($context->getVersion(), '1.2.0', '<')){
$installer->getConnection()->addColumn(
$installer->getTable('aqrun_helloworld_post'),
'test',
[
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL,
'nullable' => true,
'length' => '12,4',
'comment' => 'test',
'after' => 'status'
]
);
}
$installer->endSetup();
}
}
中这个类中,定义了 upgrade()
方法,它会在模块每次更新后都执行。并对对比了版本号为每个版本分开添加脚本
更新数据
和 UpgradeSchema 类一样
文件: app/code/Aqrun/HelloWorld/Setup/UpgradeData.php
<?php
namespace Aqrun\HelloWorld\Setup;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
class UpgradeData implements UpgradeDataInterface
{
protected $_postFactory;
public function __construct(
\Aqrun\HelloWrold\Model\PostFactory $postFactory
){
$this->_postFactory = $postFactory;
}
public function(
ModuleDataSetupInterface $setup,
ModuleContextInterface $context
){
if(version_compare($context->getVersion(), '1.2.0', '<')) {
$data = [
'name' => '测试文章标题',
'post_content' => '测试正文内容好多内容',
'url_key' => '/module-test/test-post-title.html',
'tags' => '测试,内容,标题',
'status' => 1
];
$post = $this->_postFactory->create();
$post->addData($data)->save()
}
}
}
循环脚本 Recurring
循环脚本在每次执行 php bin/magento setup:upgrade
命令后安装脚本运行完成时都会运行。
这个脚本和 InstallSchema
类一样定义,只是类不同。代码实例可以查看系统文件: vendor/magento/module-indexer/Setup/Recurring.php
卸载脚本
系统提供了卸载模块的功能,可以删除所有模块相关的数据表和数据,就如同模块没有安装过一样。如下示例:
文件: app/code/Aqrun/HelloWorld/Setup/Uninstall.php
<?php
namespace Aqrun\HelloWorld\Setup;
use Magento\Framework\Setup\UninstallInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
class Uninstall implements UninstallInterface
{
public function uninstall(
SchemaSetupInterface $setup,
ModuleContextInterface $context
){
$installer = $setup;
$installer->startSetup();
$installer->getConnection()->dropTable($installer->getTable('aqrun_helloworld_post'));
$installer->endSetup();
}
}