http://inchoo.net/magento/creating-an-eav-based-models-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
<?phpclass 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
<?phpclass 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
<?phpclass 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.
<?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' );}
就是这样。虽然简单,有一些打字工作要做为基础的模型得到的EAV功能。希望它可以帮助别人。
Finally, you can test your model and it’s collection by running the following somewhere in your code: