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?

  • 相关阅读:
    基于IDEA+Maven+SpringMVC的入门web程序分析(一)
    Spring之路----chapter03 高级装配
    Spring之路---chapter02装配Bean
    Spring之路----Chapter01 Spring之旅
    实用网址-项目的创建、Idea打开Maven项目、Idea打开Eclipse项目
    Git之路-2017年9月8日14:37:01
    Redis入门指南-笔记-进阶
    DenyHosts 阻止SSH暴力攻击
    某cms最新版前台RCE漏洞(无需任何权限)2020-03-15
    通过Joomla的两次RCE漏洞看session反序列化
  • 原文地址:https://www.cnblogs.com/phplover/p/3137381.html
Copyright © 2011-2022 走看看