zoukankan      html  css  js  c++  java
  • Magento学习笔记2 createEntityType方法失效!

    Test Case

    In our module we have a setup file that is very basic:

    /app/code/local/CompanyName/{ModuleName}/sql/{modulename}_setup/mysql4-install-1.0.0.php

    1
    2
    3
    4
    5
    6
    
    /* @var $installer Mage_Eav_Model_Entity_Setup */
    $installer = $this->startSetup();
     
    $installer->createEntityTables(
        $this->getTable('module_entity')
    );

    The above results in:

    1
    
    Mage_Eav_Exception: Can't create table: module_entity

    The Solution

    First some debugging. In the createEntityTables() method, you’ll see the following near the end:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    $connection->beginTransaction();
    try { 
        foreach ($tables as $tableName => $table) {
            $connection->createTable($table);
        }
        $connection->commit();
    } catch (Exception $e) {
       Zend_Debug::dump($e->getMessage());
       $connection->rollBack();
       throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Can\'t create table: %s', $tableName));
    }

    Line 8 was added because the default exception is useless. Here we see the underlying problem:

    1
    
    User Error: DDL statements are not allowed in transactions

    So now we have more digging. If you follow $connection->commit() you’ll notice the following method is called:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    /**
     * Check transaction level in case of DDL query
     *
     * @param string|Zend_Db_Select $sql
     * @throws Zend_Db_Adapter_Exception
     */
    protected function _checkDdlTransaction($sql)
    {
        if (is_string($sql) && $this->getTransactionLevel() > 0) {
            $startSql = strtolower(substr(ltrim($sql), 0, 3));
            if (in_array($startSql, $this->_ddlRoutines)) {
                trigger_error(Varien_Db_Adapter_Interface::ERROR_DDL_MESSAGE, E_USER_ERROR);
            }
        }
    }

    $this->_ddlRoutines is an array of three-letter strings of common DDL commands (CREATE, DROP, etc).

    Putting it all together, the problem is that MySQL is not able to roll back DDL transactions. The easy fix would be to comment out the trigger_error method, since this would allow all other transactions to be rolled back in case of a problem. This is an issue of course since it’s a core file. Funny enough, in this bug report Magento Team recommends this as a solution.

    For a method that is only used by module developers, this doesn’t look like sound advice. (If you take a peek in core files, this method isn’t used) Instead you have two options. The first is to do what the core does: create abstracted SQL (a major pain!) -

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    // Example of MySQL API
    /**
     * Create table array('catalog/product', 'decimal')
     */
    $table = $installer->getConnection()
        ->newTable($installer->getTable(array('catalog/product', 'decimal')))
        ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
            'identity'  => true,
            'nullable'  => false,
            'primary'   => true,
            ), 'Value ID')
        ->addColumn(...

    If you are partial to saving time in the long run, just extend the method instead. You’ll create a new helper file below, and you’ll be copying the entire createEntityTables() method into your helper file. (For brevity, only a portion of the code in the method is shown — you’ll need to comment out two lines)

    app/code/local/{CompanyName}/{ModuleName}/Setup/Helper.php

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    <?php
     
    class CompanyName_ModuleName_Setup_Helper extends Mage_Eav_Model_Entity_Setup
    {
        public function createEntityTables($baseTableName, array $options = array())
        {
            ...
     
            /**
             * Remove transaction code due to issues with errors.
             */
            //$connection->beginTransaction();
            try { 
                foreach ($tables as $tableName => $table) {
                    $connection->createTable($table);
                }
                $connection->commit();
           } catch (Exception $e) {
               //$connection->rollBack();
               throw Mage::exception('Mage_Eav', Mage::helper('eav')->__('Can\'t create table: %s', $tableName));
           }
        }
    }

    Note that you might not be able to rely on createEntityTables() long. In the same bug report listed above, Mage Team goes on to say this could be deprecated in the future since the core doesn’t make use of the method. Which begs the question… why doesn’t it?

  • 相关阅读:
    多播(组播)与广播的技术实现
    (转)单播、多播(组播)和广播的区别
    (转)简述负载均衡&CDN技术
    当领导得学会骂下属的艺术
    CSDN首页> 云计算 孙玄:解析58同城典型技术架构及演变
    VMware网络连接 桥接、NAt、host-only模式 .
    dajian
    [Android开发常见问题-4] RunTime.exec()如何以root权限执行多条指令?
    Android获取Root权限之后的静默安装实现代码示例分析
    Android
  • 原文地址:https://www.cnblogs.com/phplover/p/3137381.html
Copyright © 2011-2022 走看看