Creating an EAV based model(s) in Magento

转自: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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值