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?

  • 相关阅读:
    TP5 自带封装分页查询
    TP5 接口 前面拼接 当前域名
    button按钮点击后过段时间不能点击-验证码(刷新后失效)
    关于PHP -session 的 A session had already been started – ignoring session_start() 错误
    301 Moved Permanently
    PHP实现远程下载图片与 图片接口定义
    在TP框架的前端中 想引用 PHP的函数
    流程控制语句2
    流程控制语句
    数据库查询数据2
  • 原文地址:https://www.cnblogs.com/phplover/p/3137381.html
Copyright © 2011-2022 走看看