【问题标题】:ALTER TABLE in Magento setup script without using SQLMagento 设置脚本中的 ALTER TABLE 不使用 SQL
【发布时间】:2010-11-30 15:54:46
【问题描述】:

Jonathon Day

"更新不应该是 SQL 命令”。我没遇到过 任何 DDL 或 DML 语句不能 通过 Magento 的配置执行 结构。

(在问题How can I migrate configuration changes from development to production environment?

我想知道如何最好地以这种方式在表中添加/修改/删除列或索引,但不依赖 SQL?有可能吗?

此外,还有哪些动作只能在 SQL 中完成?

【问题讨论】:

  • 你不能不使用 SQL 来修改 sql 数据库,但是你可以做二进制差异和合并,magento 有一个很好的方法来处理更新脚本中的更新。配置更改可以作为 magento 中的设置/升级脚本处理。其他选项是在实时环境中应用配置更改并将数据库复制到开发环境
  • @Anton S - 正是我要问的那些更新脚本。
  • 如果你这样做了,那么请尝试使用 Magento 提供的方法(或 zend 抽象),因为它们是计数表前缀和其他配置选项,它们可能依赖于在每个安装中并不总是相同的其他设置

标签: php sql magento installation entity-attribute-value


【解决方案1】:

您可以在安装脚本中使用这些方法:

  • 使用Varien_Db_Ddl_Table类创建新表,可以结合$this->getConnection()->createTable($tableObject)配置所有字段、键、关系 示例:

    /* @var $this Mage_Core_Model_Resource_Setup */
    $table = new Varien_Db_Ddl_Table();
    $table->setName($this->getTable('module/table'));
    $table->addColumn('id', Varien_Db_Ddl_Table::TYPE_INT, 10, 
                      array('unsigned' => true, 'primary' => true));
    
    $table->addColumn('name', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255);
    $table->addIndex('name', 'name');
    $table->setOption('type', 'InnoDB');
    $table->setOption('charset', 'utf8');
    
    $this->getConnection()->createTable($table);
    
  • 使用设置连接($this->getConnection())方法:

    • addColumn() 方法将新列添加到现有表。它有这样的参数:
      • $tableName - 应该修改的表名
      • $columnName- 应该添加的列名
      • $definition - 列的定义(INT(10)DECIMAL(12,4) 等)
    • addConstraint() 方法创建一个新的约束外键。它有这样的参数
      • $fkName - 外键名,每个数据库唯一,如果不指定FK_前缀,会自动添加
      • $tableName - 添加外键的表名
      • $columnName - 应该引用另一个表的列名,如果您有复杂的外键,请使用逗号指定多个列
      • $refTableName - 将被处理的外部表名
      • $refColumnName - 外部表中的列名
      • $onDelete - 在外部表中删除行的操作。可以是空字符串(什么都不做)、cascadeset null。该字段是可选的,如果不指定,将使用cascade值。
      • $onUpdate 对外部表中行键更新的操作。可以是空字符串(什么都不做)、cascadeset null。该字段是可选的,如果不指定,将使用cascade值。
      • $purge - 添加外键后启用行清理的标志(例如删除未引用的记录)
    • addKey() 方法用于向表中添加索引。它有这样的参数:
      • $tableName - 应该添加索引的表名
      • $indexName - 索引名称
      • $fields - 索引中使用的列名
      • $indexType - 索引类型。可能的值为:indexuniqueprimaryfulltext。该参数是可选的,所以默认值为index
    • dropColumn() 方法用于从现有表中删除列。它有这样的参数:
      • $tableName - 应该修改的表名
      • $columnName- 应该删除的列名
    • dropForeignKey() 方法用于删除外键。它有这样的参数:
      • $tableName - 删除外键的表名
      • $fkName - 外键名
    • dropKey() 方法用于删除表索引。它有这样的参数:
      • $tableName - 应该删除索引的表名
      • $keyName - 索引名称
    • modifyColumn 方法用于修改表中现有的列。它有这样的参数:
      • $tableName - 应该修改的表名
      • $columnName- 应该重命名的列名
      • $definition - 列的新定义(INT(10)DECIMAL(12,4) 等)
    • changeColumn 方法用于修改和重命名表中现有的列。它有这样的参数:
      • $tableName - 应该修改的表名
      • $oldColumnName- 列的旧名称,应该重命名和修改
      • $newColumnName- 列的新名称
      • $definition - 列的新定义(INT(10)DECIMAL(12,4) 等)
    • changeTableEngine 方法用于更改表引擎,例如从 MyISAM 到 InnoDB。它有这样的参数:
      • $tableName - 表名
      • $engine - 新引擎名称(MEMORYMyISAMInnoDB 等)

您也可以使用tableColumnExists 方法来检查列的存在。

这不是您可以摆脱直接 SQL 查询编写的方法的完整列表。您可以在 Varien_Db_Adapter_Pdo_MysqlZend_Db_Adapter_Abstract 课程中找到更多信息。

不要犹豫,看看你将要使用的类定义,你可以为自己找到很多有趣的东西:)

【讨论】:

  • 很高兴知道那些在那里!
  • 谢谢伊万。这是一个很棒的方法参考!我看过 Mage_* 课程并没有看到这样的东西,所以开始绝望。希望我的更新脚本将来会更整洁。
  • @clockworkgeek 欢迎。顺便说一句,Mage 只包含 Magento 的 MVC 实现,用于处理 FileSystem、DB、Sockets 的 API,不同的文件格式放在 lib/Varien 下,并且很多类都是从 Zend Framework 扩展而来的
  • @Jonathan 希望 Magento 2.0 对开发人员更加友好,尤其是在数据库升级方面。但当然它只是扩展 Zend_Db。使用 Doctrine 2.0 orm 可以解决这个问题,但它需要从头开始重写 Magento :)
  • @demonkoryu 我在 1.3 中看不到它,但在 1.4 中看到它。
【解决方案2】:

任何 Magento 更新都不应包含 SQL 的想法是基于

  1. Magento 对象在您的数据库/数据存储层之上提供抽象

  2. 您应该使用抽象来更新 Magento,这可以确保如果 Magento 团队更改了对象与数据存储的交互方式,您的更新仍然有效(假设核心团队维护对象隐含的原始“合同”方法)

所以,问题在于ALTER TABLE 语句直接更改数据存储。如果您只订阅上述两个想法,则永远不应该更改数据存储。 (在添加列或索引的情况下,意味着仅使用 EAV 模型,使用设置资源来管理更改,并接受 Magento 的索引)。

一个好的一般经验法则是,如果您要更改或添加到一些核心 Magento 功能(产品、评论等),请远离直接更改数据库结构,除非您愿意在期间仔细管理它升级。

如果您正在构建新的对象和功能,请使用您想要创建的任何 SQL,并通过设置资源更改您的表。如果您查看安装程序/升级文件,您会发现核心 Magento 团队自己执行此操作。

【讨论】:

  • 我非常喜欢您在知识库中的文章 :) 但并非所有 magento(关键和最常用)对象都不能使用 EAV 进行扩展,因为它们是平面表结构(如 order 和 quote ) 并向其中添加变量需要使用更改表,即使您通过提供的方法这样做也是如此。回滚此类更改需要额外的数据完整性和管理步骤。
  • @Anton,顺便说一下,订单和报价在设置脚本中有伪 EAV API。例如,为订单实体调用addAttribute 方法将导致在order_flat 表中创建一个新列。
  • @Anton 模块安装类应该从 Mage_Sales_Model_Mysql4_Setup 扩展以实现此功能
  • @Alan 我的回答中提出的方法不在第一个 Magento 版本中,因此“Core”中有很多旧代码,似乎没有人会在最近的将来对其进行重构。
  • @Ivan:同意,尽管我坚持我的观点。做某事的“正确”方式是 1. 它有效吗? 2.你愿意支持吗?
【解决方案3】:

要使用外键更改表并添加列,我已经使用 Magento CE v1.6.1.0 成功使用了它:

// Alter table to add column
$installer->getConnection()

        ->addColumn(
            $installer->getTable('modulekey/model'), 
            'column_name',  
            array(
                'type'      => Varien_Db_Ddl_Table::TYPE_INTEGER,
                'length'    => null,
                'unsigned'  => true,
                'nullable'  => true,
                'comment'   => 'Foreign key'
            )
        );

// Add foreign key constraint
$installer->getConnection()

        ->addForeignKey(
            $installer->getFkName( 
                'modulekey/model',  'column_name',
                'modulekey/foreign_model',  'foreign_column_name'
            ),
            $installer->getTable('modulekey/model'), 
            'column_name',
            $installer->getTable('modulekey/foreign_model'),
            'foreign_column_name',
            Varien_Db_Ddl_Table::ACTION_SET_NULL, 
            Varien_Db_Ddl_Table::ACTION_SET_NULL
        );

这些是来自Varien_Db_Adapter_Pdo_Mysql 的方法。

【讨论】:

  • 除了伊万的回答外,知道如何做也很重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 2011-07-17
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多