9.如何创建安装、升级、卸载脚本

Magento 2 开发目录

本文主要研究一下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() 方法,并且有两个参数 SchemaSetupInterfaceModuleContextInterfaceSchemaSetupInterface 接口类型的 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();
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • Magento 2 模块开发基础部分 - 目录 通过 Magento 2 的模型可以很容易管理数据库数据,不需要写...
    子十一刻阅读 1,238评论 1 1
  • Magento 2 模块开发基础部分 - 目录 本章节讨论Magento 2后台数据网格。如你所知Magento ...
    子十一刻阅读 844评论 0 0
  • 想要深入了解magento,我们有必要回顾一下Magento的前世今生,看它是如何一步步成长起来的。 为什么有不同...
    我就是那个老邹阅读 1,105评论 0 1
  • 你的自我形象正确吗 本测验有50个形容词,请从头到尾读两次。第一次读时,如果碰到的形容词切合自己的个性或形象,就在...
    六安姐阅读 98评论 0 0
  • 求之不得 弃而不舍 所以,我们只能是朋友 你是毒酒 我也甘之如饴 你是青春的标本 我是福尔马林 当我泡你时,你还是...
    June青柠阅读 563评论 0 0