现在的位置: 首页 > 综合 > 正文

Creating an EAV based model(s) in Magento

2013年11月10日 ⁄ 综合 ⁄ 共 14845字 ⁄ 字号 评论关闭

转自:http://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/

Magento database heavily uthttp://inchoo.net/ecommerce/magento/creating-an-eav-based-models-in-magento/ilizes an Entity-Attribute-Value (EAV) data model. However, the cost of flexibility is often complexity. The process of manipulating EAV data in Magento
is often more difficult than manipulating flat relational tables.

All Magento Models inherit from the Mage_Core_Model_Abstract. Difference between simple Model or an EAV Model is its Model Resource.

To build a model with proper collection object in Magento you need 4 things:

  • model class
  • resource class
  • collection class
  • install script (the one found under mymodule_setup folder of your extension)

To extend this little further there is one more file you would most likely need when building an EAV based model, the Setup.php which extends from Mage_Eav_Model_Entity_Setup. You would need to implement the getDefaultEntities() method in it as this is what’s
called during the extension installation in Magento.

Imagine your module is called Phonebook and put into the /Inchoo namespace under the local code pool. Logically you would need a model class like User which represents single entry into the phonebook. With this in mind you already need a structure like:

  • app/etc/modules/Inchoo_Phonebook.xml
  • app/code/local/Inchoo/Phonebook/etc/config.xml
  • app/code/local/Inchoo/Phonebook/Model/User.php
  • app/code/local/Inchoo/Phonebook/Model/Resource/User.php
  • app/code/local/Inchoo/Phonebook/Model/Resource/User/Collection.php
  • app/code/local/Inchoo/Phonebook/Model/Resource/Setup.php
  • app/code/local/Inchoo/Phonebook/sql/inchoo_phonebook_setup/install-1.0.0.0.php

Now that we outlined the file structure, let’s get down to it and see what the content of files should look like in order for it to work.

app/etc/modules/Inchoo_Phonebook.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Inchoo_Phonebook>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core />
                <Mage_Eav />
            </depends>
        </Inchoo_Phonebook>
    </modules>
</config>

app/code/local/Inchoo/Phonebook/etc/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Inchoo_Phonebook>
            <version>1.0.0.0</version>
        </Inchoo_Phonebook>
    </modules>
    <global>
        <models>
            <inchoo_phonebook>
                <class>Inchoo_Phonebook_Model</class>
                <resourceModel>inchoo_phonebook_resource</resourceModel>
            </inchoo_phonebook>
            <inchoo_phonebook_resource>
                <class>Inchoo_Phonebook_Model_Resource</class>
                <entities>
                    <user>
                        <table>inchoo_phonebook_user_entity</table>
                    </user>
                    <user_entity_varchar>
                        <table>inchoo_phonebook_user_entity_varchar</table>
                    </user_entity_varchar>
                    <user_entity_text>
                        <table>inchoo_phonebook_user_entity_text</table>
                    </user_entity_text>
                    <user_entity_int>
                        <table>inchoo_phonebook_user_entity_int</table>
                    </user_entity_int>
                </entities>
            </inchoo_phonebook_resource>
        </models>
        <resources>
            <inchoo_phonebook_setup>
                <setup>
                    <module>Inchoo_Phonebook</module>
                    <class>Inchoo_Phonebook_Model_Resource_Setup</class>
                </setup>
            </inchoo_phonebook_setup>
            <inchoo_phonebook_write>
                <connection>
                    <use>default_write</use>
                </connection>
            </inchoo_phonebook_write>
            <inchoo_phonebook_read>
                <connection>
                    <use>default_read</use>
                </connection>
            </inchoo_phonebook_read>
        </resources>
    </global>
</config>

app/code/local/Inchoo/Phonebook/Model/User.php

<?php
class Inchoo_Phonebook_Model_User extends Mage_Core_Model_Abstract
{
    /**
* Maps to the array key from Setup.php::getDefaultEntities()
*/
    const ENTITY = 'inchoo_phonebook_user';
    
    protected $_eventPrefix = 'inchoo_phonebook';
    protected $_eventObject = 'user';
    function _construct()
    {
        $this->_init('inchoo_phonebook/user');
    }
}

app/code/local/Inchoo/Phonebook/Model/Resource/User.php

<?php
class Inchoo_Phonebook_Model_Resource_User extends Mage_Eav_Model_Entity_Abstract
{
    public function __construct()
    {
        $resource = Mage::getSingleton('core/resource');
        
        $this->setType(Inchoo_Phonebook_Model_User::ENTITY);
        $this->setConnection(
            $resource->getConnection('inchoo_phonebook_read'),
            $resource->getConnection('inchoo_phonebook_write')
        );
    }
}

app/code/local/Inchoo/Phonebook/Model/Resource/User/Collection.php

<?php
class Inchoo_Phonebook_Model_Resource_User_Collection extends Mage_Eav_Model_Entity_Collection_Abstract
{
    protected function _construct()
    {
        $this->_init('inchoo_phonebook/user');
    }
    
    protected function _initSelect()
    {
        $this->getSelect()->from(array('e' => $this->getEntity()->getEntityTable()));
        if ($this->getEntity()->getTypeId()) {
            /**
* We override the Mage_Eav_Model_Entity_Collection_Abstract->_initSelect()
* because we want to remove the call to addAttributeToFilter for 'entity_type_id'
* as it is causing invalid SQL select, thus making the User model load failing.
*/
            //$this->addAttributeToFilter('entity_type_id', $this->getEntity()->getTypeId());
        }
     
        return $this;
    }
}

app/code/local/Inchoo/Phonebook/Model/Resource/Setup.php

<?php
class Inchoo_Phonebook_Model_Resource_Setup extends Mage_Eav_Model_Entity_Setup {
    public function getDefaultEntities() {
        return array(
            Inchoo_Phonebook_Model_User::ENTITY => array(
                'entity_model' => 'inchoo_phonebook/user',
                'table' => 'inchoo_phonebook/user', /* Maps to the config.xml > global > models > inchoo_phonebook_resource > entities > user */
                'attributes' => array(
                    'first_name' => array(
                        'type' => 'varchar',
                        'label' => 'First name',
                        'input' => 'text',
                        'required' => true,
                        'sort_order' => 10,
                        'position' => 10,
                        'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
                    ),
                    'last_name' => array(
                        'type' => 'varchar',
                        'label' => 'Last name',
                        'input' => 'text',
                        'required' => true,
                        'sort_order' => 20,
                        'position' => 20,
                        'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
                    ),
                    'email' => array(
                        'type' => 'varchar',
                        'label' => 'Email',
                        'input' => 'text',
                        'required' => true,
                        'sort_order' => 30,
                        'position' => 30,
                        'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
                    ),
                    'address' => array(
                        'type' => 'text',
                        'label' => 'Address',
                        'input' => 'multiline',
                        'sort_order' => 40,
                        'multiline_count' => 2,
                        'validate_rules' => 'a:2:{s:15:"max_text_length";i:255;s:15:"min_text_length";i:1;}',
                        'position' => 40,
                        'required' => false,
                        'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
                    ),
                    'is_active' => array(
                        'type' => 'int',
                        'label' => 'Is Active',
                        'input' => 'text',
                        'required' => false,
                        'sort_order' => 50,
                        'position' => 50,
                        'required' => false,
                        'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
                    ),
                )
            )
        );
    }
}

app/code/local/Inchoo/Phonebook/sql/inchoo_phonebook_setup/install-1.0.0.0.php

<?php
/* @var $installer Inchoo_Phonebook_Model_Resource_Setup */
$installer = $this;
$installer->startSetup();
/* Create table 'inchoo_phonebook/user' */
$table = $installer->getConnection()
    ->newTable($installer->getTable('inchoo_phonebook/user'))
    ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity' => true,
        'unsigned' => true,
        'nullable' => false,
        'primary' => true,
        ), 'Entity ID')
    ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
        ), 'Creation Time')
    ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
        ), 'Update Time')
    ->setComment('Inchoo Phonebook User Table');
$installer->getConnection()->createTable($table);
/* Create table 'inchoo_phonebook/user_entity_varchar' */
$table = $installer->getConnection()
    ->newTable($installer->getTable('inchoo_phonebook/user_entity_varchar'))
    ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity' => true,
        'nullable' => false,
        'primary' => true,
        ), 'Value Id')
    ->addColumn('entity_type_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Type Id')
    ->addColumn('attribute_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Attribute Id')
    ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Store ID')
    ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Id')
    ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
        ), 'Value')
    ->addIndex(
        $installer->getIdxName(
            'inchoo_phonebook_user_entity_varchar',
            array('entity_id', 'attribute_id', 'store_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('entity_id', 'attribute_id', 'store_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_varchar', array('attribute_id')),
        array('attribute_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_varchar', array('store_id')),
        array('store_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_varchar', array('entity_id')),
        array('entity_id'))
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_varchar', 'attribute_id', 'eav/attribute', 'attribute_id'),
        'attribute_id', $installer->getTable('eav/attribute'), 'attribute_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_varchar', 'entity_id', 'inchoo_phonebook/user', 'entity_id'),
        'entity_id', $installer->getTable('inchoo_phonebook/user'), 'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_varchar', 'store_id', 'core/store', 'store_id'),
        'store_id', $installer->getTable('core/store'), 'store_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->setComment('Inchoo Phonebook User Entity Varchar');
$installer->getConnection()->createTable($table);
/* Create table 'inchoo_phonebook/user_entity_int' */
$table = $installer->getConnection()
    ->newTable($installer->getTable('inchoo_phonebook/user_entity_int'))
    ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity' => true,
        'nullable' => false,
        'primary' => true,
        ), 'Value Id')
    ->addColumn('entity_type_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Type Id')
    ->addColumn('attribute_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Attribute Id')
    ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Store ID')
    ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Id')
    ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
        ), 'Value')
    ->addIndex(
        $installer->getIdxName(
            'inchoo_phonebook_user_entity_int',
            array('entity_id', 'attribute_id', 'store_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('entity_id', 'attribute_id', 'store_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_int', array('attribute_id')),
        array('attribute_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_int', array('store_id')),
        array('store_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_int', array('entity_id')),
        array('entity_id'))
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_int', 'attribute_id', 'eav/attribute', 'attribute_id'),
        'attribute_id', $installer->getTable('eav/attribute'), 'attribute_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_int', 'entity_id', 'inchoo_phonebook/user', 'entity_id'),
        'entity_id', $installer->getTable('inchoo_phonebook/user'), 'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_int', 'store_id', 'core/store', 'store_id'),
        'store_id', $installer->getTable('core/store'), 'store_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->setComment('Inchoo Phonebook User Entity Int');
$installer->getConnection()->createTable($table);
/* Create table 'inchoo_phonebook/user_entity_text' */
$table = $installer->getConnection()
    ->newTable($installer->getTable('inchoo_phonebook/user_entity_text'))
    ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity' => true,
        'nullable' => false,
        'primary' => true,
        ), 'Value Id')
    ->addColumn('entity_type_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Type Id')
    ->addColumn('attribute_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Attribute Id')
    ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Store ID')
    ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned' => true,
        'nullable' => false,
        'default' => '0',
        ), 'Entity Id')
    ->addColumn('value', Varien_Db_Ddl_Table::TYPE_TEXT, 255, array(
        ), 'Value')
    ->addIndex(
        $installer->getIdxName(
            'inchoo_phonebook_user_entity_text',
            array('entity_id', 'attribute_id', 'store_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('entity_id', 'attribute_id', 'store_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_text', array('attribute_id')),
        array('attribute_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_text', array('store_id')),
        array('store_id'))
    ->addIndex($installer->getIdxName('inchoo_phonebook_user_entity_text', array('entity_id')),
        array('entity_id'))
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_text', 'attribute_id', 'eav/attribute', 'attribute_id'),
        'attribute_id', $installer->getTable('eav/attribute'), 'attribute_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_text', 'entity_id', 'inchoo_phonebook/user', 'entity_id'),
        'entity_id', $installer->getTable('inchoo_phonebook/user'), 'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName('inchoo_phonebook_user_entity_text', 'store_id', 'core/store', 'store_id'),
        'store_id', $installer->getTable('core/store'), 'store_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->setComment('Inchoo Phonebook User Entity Text');
$installer->getConnection()->createTable($table);
$installer->endSetup();
$installer->installEntities();

For each attribute type like “varchar”, “text”, “int”… you need to create a corresponding table like inchoo_phonebook_user_entity_varchar, inchoo_phonebook_user_entity_text, inchoo_phonebook_user_entity_int. Study the install-1.0.0.0.php and the config.xml
file to see how to get that one done.

Finally, you can test your model and it’s collection by running the following somewhere in your code:

<?php
$phonebookUser = Mage::getModel('inchoo_phonebook/user');
$phonebookUser->setFristname('John');
$phonebookUser->setLastname('Doe');
$phonebookUser->setEmail('john.doe@magento.com');
$phonebookUser->setAddress('Sample address line here');
$phonebookUser->setIsActive(true);
$phonebookUser->save();
Zend_Debug::dump($phonebookUser->debug(), '$phonebookUser');
$users = Mage::getModel('inchoo_phonebook/user')->getCollection();
foreach($users as $user) {
    Zend_Debug::dump($user->debug(), '$user');
}

And that’s it. Although simple, there is some typing to be done in order to get the EAV based model functional. Hope it helps someone.

Cheers.

抱歉!评论已关闭.