Magento开发文档(六):Magento模型启动资源

在所有快节奏开发部署的项目里,保持开发环境与生产环境的数据库同步是一件非常头疼的事情。Magento内置了版本资源移植脚本,能够帮助开发团队在开发过程中很好的解决这个问题。

Magento模型与ORM基础一文中,我们为Weblog模块创建了一个模型,因为演示目的,当时手动创建的数据库。这次,我们为模型创建一个启动资源(Setup Resource),让Magento自动创建表。接下来,我们还会创建一个升级安装资源脚本,从而实现模型的自动升级。本节介绍的内容大概分为以下几步。

  • 添加启动资源配置文件
  • 创建启动资源类文件
  • 创建安装脚本
  • 创建升级脚本

添加启动资源配置文件

继续使用上一篇教程中创建的weblog模块。在<resources />节点中,添加下列配置文件,

<resources>
    <!-- ... -->
    <weblog_setup>
        <setup>
            <module>Magentotutorial_Weblog</module>
            <class>Magentotutorial_Weblog_Model_Resource_Mysql4_Setup</class>
        </setup>
        <connection>
            <use>core_setup</use>
        </connection>
    </weblog_setup>
    <!-- ... -->
</resources>

<weblog_setup>标签用来用来识别该启动资源。Magento建议该命名使用”模块名_setup”的格式。<module />标签必须包含当前“命名空间_模块名”。<class />指定我们为该模块创建的启动资源类名。对于简单的启动资源脚本,我们不需要创建自定义的类文件,当然应用自定义的启动资源脚本,更灵活,更易于扩展。

添加上述内容到配置文件之后,清空缓存,浏览Magento的任意界面,系统将会抛出如下异常,

Fatal error: Class ‘Magentotutorial_Weblog_Model_Resource_Mysql4_Setup’ not found in

Magento试图实例化我们刚刚在配置文件中指定的启动资源类,系统提示无法找到该类。我们在如下路径创建该文件。

File: app/code/local/Magentotutorial/Weblog/Model/Resource/Mysql4/Setup.php

class Magentotutorial_Weblog_Model_Resource_Mysql4_Setup extends Mage_Core_Model_Resource_Setup {
}

完成之后,重新刷新页面,页面就能够正常显示了。到这里,启动资源配置文件初步完成。

创建安装脚本

接下来,开始创建安装脚本。该脚本会包含CREATE TABLE或其他SQL代码,用来初始化该模块。首先,回忆下配置文件,

<modules>
    <Magentotutorial_Weblog>
        <version>0.1.0</version>
    </Magentotutorial_Weblog>
</modules>

这部分是所有配置文件必须的,用来识别一个模块的版本号。安装脚本的命名就需要依据此版本号。我们假设当前weblog模块的版本号为0.1.0。

在下列路径创建启动脚本,并暂时写入下列代码。

File: app/code/local/Magentotutorial/Weblog/sql/weblog_setup/mysql4-install-0.1.0.php

echo 'Running This Upgrade: '.get_class($this)."\n <br /> \n";
die("Exit for now");

上述路径的weblog_setup部分必须匹配在配置文件中设置的<weblog_setup>标签。0.1.0匹配的是在模块中填写的<version>版本号。清空Magento缓存,访问任意页面,会看到如下内容,

unning This Upgrade: Magentotutorial_Weblog_Model_Resource_Mysql4_Setup
Exit for now

这说明安装脚本正常运行了。这里为了演示目的,没有加入SQL代码,我们只专注于安装机制本身。现在移除die()语句,保留以下部分。

echo 'Running This Upgrade: '.get_class($this)."\n <br /> \n";

刷新页面,页面会显示升级成功的消息。再次刷新,就会显示正常页面了。

启动资源版本

Magento的启动资源能够自动运行安装脚本,你只需要将正确的代码放入安装脚本,或者升级脚本当中。由于版本号的原因,你可以保留所有的脚本,便于查看各个版本中数据库结构的变动。

使用你最喜欢的数据库客户端,查看core_resource表,

mysql> select * from core_resource;
+————————-+———+
| code�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | version |
+————————-+———+
| adminnotification_setup | 1.0.0�0�2�0�2 |
| admin_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.1�0�2�0�2 |
| amazonpayments_setup�0�2�0�2�0�2 | 0.1.2�0�2�0�2 |
| api_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.1�0�2�0�2 |
| backup_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| bundle_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.7�0�2�0�2 |
| catalogindex_setup�0�2�0�2�0�2�0�2�0�2 | 0.7.10�0�2 |
| cataloginventory_setup�0�2 | 0.7.5�0�2�0�2 |
| catalogrule_setup�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.7�0�2�0�2 |
| catalogsearch_setup�0�2�0�2�0�2�0�2 | 0.7.6�0�2�0�2 |
| catalog_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.69�0�2 |
| checkout_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.9.3�0�2�0�2 |
| chronopay_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| cms_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.8�0�2�0�2 |
| compiler_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| contacts_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.0�0�2�0�2 |
| core_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.13�0�2 |
| cron_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.1�0�2�0�2 |
| customer_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.11�0�2 |
| cybermut_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| cybersource_setup�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| dataflow_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.4�0�2�0�2 |
| directory_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.5�0�2�0�2 |
| downloadable_setup�0�2�0�2�0�2�0�2�0�2 | 0.1.14�0�2 |
| eav_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.13�0�2 |
| eway_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| flo2cash_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.1�0�2�0�2 |
| giftmessage_setup�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| googleanalytics_setup�0�2�0�2 | 0.1.0�0�2�0�2 |
| googlebase_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.1�0�2�0�2 |
| googlecheckout_setup�0�2�0�2�0�2 | 0.7.3�0�2�0�2 |
| googleoptimizer_setup�0�2�0�2 | 0.1.2�0�2�0�2 |
| ideal_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| log_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.6�0�2�0�2 |
| newsletter_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.0�0�2�0�2 |
| oscommerce_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.8.10�0�2 |
| paybox_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.3�0�2�0�2 |
| paygate_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| payment_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| paypaluk_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| paypal_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| poll_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| productalert_setup�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| protx_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| rating_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| reports_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.7�0�2�0�2 |
| review_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.4�0�2�0�2 |
| salesrule_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.7�0�2�0�2 |
| sales_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.9.38�0�2 |
| sendfriend_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| shipping_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| sitemap_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| strikeiron_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.9.1�0�2�0�2 |
| tag_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.2�0�2�0�2 |
| tax_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.8�0�2�0�2 |
| usa_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.0�0�2�0�2 |
| weblog_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |
| weee_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.13�0�2�0�2�0�2 |
| wishlist_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.7.4�0�2�0�2 |
+————————-+———+
59 rows in set (0.00 sec)

该表包含所有已安装的模块及其版本号,可以在底部看到我们创建的weblog模块,

| weblog_setup�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2�0�2 | 0.1.0�0�2�0�2 |

该表的记录也是Magento知道如何避免重复运行安装、更新脚本的原因。如果在开发阶段,你想让系统重新运行安装脚本,可以从该表中删除相应的模块记录。在上面的演示过程中,系统运行了weblog的安装脚本,当时脚本中还不包含任何SQL内容,这里我们删除weblog_setup记录,并在安装脚本中写入实际的SQL代码,创建weblog的表。

首先,运行一下语句删除weblog_setup记录(当然,你可以在phpmyadmin中直接点击删除按钮),

DELETE from core_resource where code = ‘weblog_setup’;

然后,删除我们在《Magento模型与ORM基础》建立的blog_posts表,因为我们这里即将使用启动资源重新建立该表。

DROP TABLE blog_posts;

接着,添加下列SQL代码到启动脚本中,

$installer = $this;
$installer->startSetup();
$installer->run("
    CREATE TABLE `{$installer->getTable('weblog/blogpost')}` (
        `blogpost_id` int(11) NOT NULL auto_increment,
        `title` text,
        `post` text,
        `date` datetime default NULL,
        `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
        PRIMARY KEY�0�2 (`blogpost_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `{$installer->getTable('weblog/blogpost')}` VALUES (1,'My New Title','This is a blog post','2009-07-01 00:00:00','2009-07-02 23:12:30');
");
$installer->endSetup();

清空Magento缓存,访问任意页面,一切正常的话,重新打开数据库,会见到blog_posts表创建成功了。

Magento启动脚本详解

一起来看下这个启动脚本,首先,第一行中有个$this。

$installer = $this;

安装脚本都是在启动资源类的上下文中运行的,所以上面的$this表示的就是启动资源类。也就是说,在安装脚本中,任何对于$this的引用都是对于启动资源类对象的引用。在核心模块的启动脚本中,Magento团队都将该对象的引用赋值给$installer变量,当然这并不是必须的,但是从Magento团队的做法来看,这也算是一个最佳实践。

继续解析启动脚本,上面的代码前后调用了两个方法

$installer->startSetup();
//...
$instaler->endSetup();

如果你看过Mage_Core_Model_Resource_Setup类(启动资源类继承自该类),路径位于app/code/core/Mage/Core/Model/Resource/Setup.php,你会发现这些方法进行了一些基础的SQL操作。

public function startSetup() {
    $this->_conn->multi_query("SET SQL_MODE='';
        SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
        SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
    ");
    return $this;
}

public function endSetup() {
    $this->_conn->multi_query("
        SET SQL_MODE=IFNULL(@OLD_SQL_MODE,'');
        SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS,0);
    ");
    return $this;
}

这些基本语句大家应该很熟悉了,就不多做解释。接着再看启动脚本中的最后一块,run()方法。

$installer->run(...);

该方法的参数包含创建数据库表的所有SQL语句,就想在命令行中键入的命令一样。可以在这个参数中指定任意数量的SQL语句,只需要用分号隔开每条SQL语句即可。当然,可能你还注意到了下面这个方法,

$installer->getTable('weblog/blogpost');

getTable()方法需要一个Magento模型URI作为参数,返回表名。当然你也可以硬编码为该表的名字,这里之所以使用这个方法,主要是为了确保即使表名更改,也可以正常获取到修改后的表名。Mage_Core_Model_Resource_Setup类包含了许多类似getTable()的非常有用的助手方法。想要学习安装脚本,最后的办法就是看Magento核心代码中模块的SQL升级脚本。

模块升级

上文中已经学习了如何利用Magento启动脚本创建数据库表,如果你想更改已经存在的数据库表的结构,该如何操作呢?Magento的启动资源支持简单的版本支持,能够自动运行脚本升级模块的数据库表结构。

Magento模块的安装脚本只会运行一次,并且不会再次为这个模块运行另外一个安装脚本(当然,除非你手动从core_resource表中删除该记录)。所以,如果想更改表结构,可以创建一个升级脚本(upgrade script)。升级脚本和安装脚本非常类似,不同之处也会在下文中一一提到。

首先,在下列路径创建升级脚本并填写如下内容,

File: app/code/local/Magentotutorial/Weblog/sql/weblog_setup/mysql4-upgrade-0.1.0-0.2.0.php:

echo 'Testing our upgrade script (mysql4-upgrade-0.1.0-0.2.0.php) and halting execution to avoid updating the system version number <br />';
<span style="color: #ff0000;">die();</span>

可以看到,升级脚本与安装脚本都在同样的文件夹中,命名方式稍有不同。最明显的是,升级脚本中包含upgrade。其次,包含两个版本号,用“-”分隔开。第一个版本号(0.1.0)是我们要升级的模块的版本号。第二个(0.2.0)是当前模块要升级到的版本号。

清空Magento缓存,访问任意页面,可以看到脚本并不会运行。我们需要更新配置文件中的版本号来促发更新脚本。

<modules>
    <Magentotutorial_Weblog>
        <version>0.2.0</version>
    </Magentotutorial_Weblog>
</modules>

完成配置文件版本号修改之后,清空Magento缓存,访问任意页面,就能看到升级脚本输出了上述echo语句,注意这里使用了die()语句组织了脚本继续运行,所以core_resource表中该模块的版本号依然为0.1.0。

在进行实际的更新脚本之前,还有一个很重要的细节需要注意到。在如下路径创建另外一个升级脚本,如下。

File: app/code/local/Magentotutorial/Weblog/sql/weblog_setup/mysql4-upgrade-0.1.0-0.1.5.php:

echo 'Testing our upgrade script (mysql4-upgrade-0.1.0-0.1.5.php) and NOT halting execution <br />';

访问任意页面,你会发现,页面中会显示两个升级脚本里的内容。Magento在发现某个模块的版本号有变化时,系统会自动运行所有的升级脚本。尽管我们并没有实际创建该模块的0.1.5版本,Magento默认已经读取到了升级脚本,所以就会尝试运行。并且,系统会自动按照版本号从低版本向高版本运行。

查看下core_resource表,你会注意到Magento当前版本为0.1.5(mysql4-upgrade-0.1.0-0.1.5.php中没有die()或exit()组织脚本运行,所以当前模块的版本号已经被更新为0.1.5)。这是因为完全执行了0.1.0-0.1.5的升级,却没有完成0.1.0-0.2.0的升级。

了解这些内容之后,让我们继续。首先开始编码0.1.0-0.2.0的升级脚本。

$installer = $this;
$installer->startSetup();
$installer->run("
ALTER TABLE `{$installer->getTable('weblog/blogpost')}`
CHANGE post post text not null;
");
$installer->endSetup();
die("You'll see why this is here in a second");

完成之后访问任意页面。很好,你会发现系统没有提示你运行成功。也就是说升级脚本根本没有运行。post字段还是Null值,更明显的是die()语句也同样没有执行。为什么会这样呢?

  • weblog_setup资源的版本是0.1.0
  • 我们需要升级该模块到0.2.0
  • Magento系统查找升级脚本,其中有两个脚本需要运行,0.1.0-0.1.5和0.1.0-0.2.0。
  • Magento系统按照版本号,从低到高自动运行上述两个脚本
  • 首先运行0.1.0-0.1.5
  • 完成之后,当前weblog_setup资源的版本号是0.1.5
  • 接着运行0.1.0-0.2.0脚本,执行停止了。
  • 上步停止的原因是,weblog_setup的版本号已经被升级为0.1.5,并没有发现任何0.1.5-0.2.0这种类似的脚本,因为上述两个脚本全部指示是从0.1.0的版本开始升级。

实现这种连续升级的正确方法,应该是以下面的形式命名升级脚本,

mysql4-upgrade-0.1.0-0.1.5.php #This goes from 0.1.0 to 0.1.5
mysql4-upgrade-0.1.5-0.2.0.php #This goes 0.1.5 to 0.2.0

这样的话,Magento就能够一次性运行这两个升级脚本了。

Magento启动资源总结

本篇主要讲了如何使用Magento启动资源创建不同版本的数据库脚本,现在你应该能够大概理解核心模块中的升级脚本的含义了。对于启动资源来说,除了方便开发者做数据库升级及移植外,对于创建和修改EAV模型有着更重要的作用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值