Skip to content

Tutorial.Others III: Module Updating.zh_cn

linzongshu edited this page Jul 4, 2013 · 2 revisions

English

  1. 模块更新

安装完模块后,可能由于需求,我们需要对模块进行更新。若更新不涉及数据库,则直接将当前模块代码覆盖即可,但若需要修改数据表内容或表的字段,我们就得重新安装模块。但这种方法会使线上已有的数据全被删除,因此这时我们需要走更新流程,通过比较模块的版本号在更新文件里添加相应的代码修改数据库的字段或内容。

Pi Engine已经封装好了模块的更新方法,若模块没有创建更新文件,系统的更新方法将被调用,但这个方法根本不知道我们需要更新哪些内容。所以模块需要创建更新文件来覆盖系统的更新文件。

现在我们在src目录下创建如下目录,在更新触发时,这里的类若存在,则会被用于完成模块更新:

member
|- src
   |- Installer
       |- Action
          |- Update.php

现在我们打开Update.php并添加如下代码:

路径:usr/module/member/src/Installer/Action/Update.php

Code 9.3.1

<?php
namespace Module\Member\Installer\Action;

use Pi;
use Pi\Application\Installer\Action\Update as BasicUpdate;
use Zend\EventManager\Event;
use Pi\Application\Installer\SqlSchema;

class Update extends BasicUpdate
{
    protected function attachDefaultListeners()
    {
        $events = $this->events;
        $events->attach('update.pre', array($this, 'updateSchema'));
        parent::attachDefaultListeners();
        return $this;
    }

    public function updateSchema(Event $e)
    {
        $moduleVersion = $e->getParam('version');
        if (version_compare($moduleVersion, '1.0.1-beta.1', '>=')) {
            return true;
        }

        $sql =<<<'EOD'
CREATE TABLE `{stats}` (
`id`      int(10) unsigned        NOT NULL auto_increment,
`title`   varchar(255)            NOT NULL default '',
`url`     varchar(255)            NOT NULL default '',

PRIMARY KEY  (`id`)
);
EOD;
        SqlSchema::setType($this->module);
        $sqlHandler = new SqlSchema;
        try {
            $sqlHandler->queryContent($sql);
        } catch (\Exception $exception) {
            $result = $e->getParam('result');
            $result['db'] = array(
                'status'   => false,
                'message'  => 'SQL schema query failed: ' . $exception,
            );
            $e->setParam('result', $result);
            return false;
        }
    }
}

这个Update类需要继承自Pi\Application\Installer\Action\Update类,因此需要引用这个类,另外更新的机制是以事件驱动的形式,所以要引用Zend\EventManager\Event,最后还要引用Pi\Application\Installer\SqlSchema类用于创建数据表。

在类Update中,首先定义了一个私有方法attachDefaultListeners(),这个方法是必须有的,它将覆盖其父类的同名方法,attachDefaultListeners()方法用于将执行更新的方法写入事件驱动,在attach()方法里,第一个参数就是事件,update.pre事件里的方法将在更新之前执行,还有update.post里的事件将在update.pre事件执行完之后执行。在代码里,我们把updateSchema()方法写入事件驱动,到时候执行更新时就会调用这个方法完成更新任务。

接下来我们还需要创建updateSchema()公有方法来完成更新。在updateSchema()方法里,首先获取了当前系统已安装的模块的版本号,然后将这个版本号与最新的版本号(即1.0.1-beta.1,这个版本号在每次修改完模块提交之前都需要修改)对比,若版本高于或等于最新版本,则不往下执行,否则,执行接下来的更新代码。在更新代码里,我们主要实例化了SqlSchema对象,并通过这个对象向数据库添加一张数据表,当然这张是属于member模块的,所以需要调用setType()方法来标识。最后若添加出错,则将错误信息保存起来,将调用setParam()方法将错误信息交由Pi Engine处理和显示。

最后还需要去module.php里更改版本号,这样在更新成功后,这个版本就会被写进数据库。

路径:usr/module/member/config/module.php

Code 9.3.2

<?php
return array(
    'meta'        => array(
        'title'         => __('Member Demo'),
        'description'   => __('A module realize user register for training'),
        'version'       => '1.0.1-beta.1',
        'license'       => 'New BSD',
        'logo'          => 'image/logo.png',
        'clonable'      => false,
    ),
    ...
);

最后进入后台Module页,在Member模块下点击Update后,可以看见模块更新成功,模块的版本号也变为1.0.1-beta.1,进入数据库可以看到多了一张数据表:

fig9-10

图9-10 通过模块更新创建数据表

模块自定义安装和卸载也和更新一样,安装的类为Install,对应的事件为install.pre和install.post,分别为安装前和安装后;卸载的类为Uninstall,对应的事件为uninstall.pre和uninstall.post,需要注意的是,安装前(卸载前)和安装后(卸载后)都是针对数据表而言,如要插入一条数据,那么方法必须得附加给install.post事件,否则表还没创建是无法插入数据的。

Clone this wiki locally