I want to create a multi-select attribute dropdown in magento's administrator section, so that I can insert the attributes values in a serialized manner into database.
Kindly note that the table to which I want to insert values is a custom one ie, I have created by own table in database. I have seen the code for multi store as be开发者_如何学Clow:
if (!Mage::app()->isSingleStoreMode()) {
$fieldset->addField('store_id', 'multiselect', array(
'name' => 'stores[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
));
}
but I am not able to use such format as my database table is custom one. Please let me know the alternate code through which I can insert values of multi select attribute to databse. thanks
As Magento has it's own way to store Store ids in the DB I would suggest following those standards. Using serialised values are not a very good idea...
YM = Your module YM_store is the new table we will create later on. YM_entity_id is the id of whatever entity you want to use here. (Eg. in Core/cms/block, "YM_entity_id" is "block_id".)
Please make sure to use the same capitalisation everywhere.
1)
You will need to create a new table to store the entity_id <> store_id map.
In your mysql4-upgrade-x.x.x-n.n.n.php file (YM/sql/YM_setup/) add the following code to create a new table:
<?php
$installer = $this;
$installer->startSetup();
$installer->run("
CREATE TABLE {$this->getTable('YM_store')} (
`YM_entity_id` smallint(6) NOT NULL default '0',
`store_id` smallint(5) NOT NULL default '0',
PRIMARY KEY (`YM_entity_id`,`store_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");
$installer->endSetup();
2)
Next step is to add this table to the module configuration: Add the following line to the config.xml (YM/etc/config.xml)
Find and add this after the last table entities:
<YM_store>
<table>YM_store</table>
</YM_store>
Make sure to change the version number in config.xml to the same as your mysql upgrade file.
3)
Next step is to add the dropdown form element to your Form.php (YM/Block/Adminhtml/YM/Edit/Form.php)
/**
* Check is single store mode
*/
if (!Mage::app()->isSingleStoreMode()) {
$fieldset->addField('store_id', 'multiselect', array(
'name' => 'stores[]',
'label' => Mage::helper('cms')->__('Store View'),
'title' => Mage::helper('cms')->__('Store View'),
'required' => true,
'values' => Mage::getSingleton('adminhtml/system_store')->getStoreValuesForForm(false, true),
));
}
else {
$fieldset->addField('store_id', 'hidden', array(
'name' => 'stores[]',
'value' => Mage::app()->getStore(true)->getId()
));
$model->setStoreId(Mage::app()->getStore(true)->getId());
}
4)
Next step is to let the controller know about the new table: In your YMController.php file (YM/controllers/Adminhtml/) you should have a saveAction function which has the following line in it:
$model->setData($data);
This is a generic save function which will make sure to send all the data from the form to the save function. (Including the values of the newly created dropdown)
5)
Next step is to add the addStoreFilter function to the Collection.php (YM/Model/Mysql4/YM) This bit of code is copied from cms/block Collection.php. You will need to change the table field names. (YM_entity_id)
/**
* Add Filter by store
*
* @param int|Mage_Core_Model_Store $store
* @return Mage_Cms_Model_Mysql4_Page_Collection
*/
public function addStoreFilter($store, $withAdmin = true)
{
if ($store instanceof Mage_Core_Model_Store) {
$store = array($store->getId());
}
$this->getSelect()->join(
array('store_table' => $this->getTable('YM/YM_store')),
'main_table.YM_entity_id = store_table.YM_entity_id',
array()
)
->where('store_table.store_id in (?)', ($withAdmin ? array(0, $store) : $store))
->group('main_table.YM_entity_id');
return $this;
}
6)
Let's add the Store to the Grid as well. In _prepareColumns() function (YM/Block/Adminhtml/YM/Grid.php) add the following lines after the column you want the stores to appear:
if (!Mage::app()->isSingleStoreMode()) {
$this->addColumn('store_id', array(
'header' => Mage::helper('cms')->__('Store View'),
'index' => 'store_id',
'type' => 'store',
'store_all' => true,
'store_view' => true,
'sortable' => false,
'filter_condition_callback'
=> array($this, '_filterStoreCondition'),
));
}
and add this function to the end of the file before the closing "}".
protected function _filterStoreCondition($collection, $column)
{
if (!$value = $column->getFilter()->getValue()) {
return;
}
$this->getCollection()->addStoreFilter($value);
}
Please note, that this code will only list "All store views" in the Grid as something missing and I couldn't figure out what. Maybe someone else will give us the answer... :)
7)
Last step is to add some functions to the YM.php so it will be able to save and load the store_ids (YM/Model/Mysql4/YM.php) The following functions are copied from cms/blocks.
BeforeSave:
/**
*
*
* @param Mage_Core_Model_Abstract $object
*/
protected function _beforeSave(Mage_Core_Model_Abstract $object)
{
if (! $object->getId()) {
$object->setCreationTime(Mage::getSingleton('core/date')->gmtDate());
}
$object->setUpdateTime(Mage::getSingleton('core/date')->gmtDate());
return $this;
}
AfterSave
/**
*
* @param Mage_Core_Model_Abstract $object
*/
protected function _afterSave(Mage_Core_Model_Abstract $object)
{
$condition = $this->_getWriteAdapter()->quoteInto('YM_entity_id = ?', $object->getId());
$this->_getWriteAdapter()->delete($this->getTable('YM/YM_store'), $condition);
foreach ((array)$object->getData('stores') as $store) {
$storeArray = array();
$storeArray['YM_entity_id'] = $object->getId();
$storeArray['store_id'] = $store;
$this->_getWriteAdapter()->insert($this->getTable('YM/YM_store'), $storeArray);
}
return parent::_afterSave($object);
}
Load. You probably don't have an identifier so I think you don't need the if statement.
public function load(Mage_Core_Model_Abstract $object, $value, $field=null)
{
if (!intval($value) && is_string($value)) {
$field = 'identifier'; // You probably don't have an identifier...
}
return parent::load($object, $value, $field);
}
AfterLoad
/**
*
* @param Mage_Core_Model_Abstract $object
*/
protected function _afterLoad(Mage_Core_Model_Abstract $object)
{
$select = $this->_getReadAdapter()->select()
->from($this->getTable('YM/YM_store'))
->where('YM_entity_id = ?', $object->getId());
if ($data = $this->_getReadAdapter()->fetchAll($select)) {
$storesArray = array();
foreach ($data as $row) {
$storesArray[] = $row['store_id'];
}
$object->setData('store_id', $storesArray);
}
return parent::_afterLoad($object);
}
getLoadSelect
/**
* Retrieve select object for load object data
*
* @param string $field
* @param mixed $value
* @return Zend_Db_Select
*/
protected function _getLoadSelect($field, $value, $object)
{
$select = parent::_getLoadSelect($field, $value, $object);
if ($object->getStoreId()) {
$select->join(array('cbs' => $this->getTable('YM/YM_store')), $this->getMainTable().'.YM_entity_id = cbs.YM_entity_id')
->where('is_active=1 AND cbs.store_id in (0, ?) ', $object->getStoreId())
->order('store_id DESC')
->limit(1);
}
return $select;
}
lookupStoreIds
/**
* Get store ids to which specified item is assigned
*
* @param int $id
* @return array
*/
public function lookupStoreIds($id)
{
return $this->_getReadAdapter()->fetchCol($this->_getReadAdapter()->select()
->from($this->getTable('YM/YM_store'), 'store_id')
->where("{$this->getIdFieldName()} = ?", $id)
);
}
Ok, if I didn't leave out anything this should work. :) Log in to the Admin area, go to System > Advanced. This should run the mysql upgrade if you set the versions right. You can check if you have a new table the DB.
Go to your entity and check if you have a new Store selection dropdown. Try saving the new values... :)
Let me know if it doesn't work. I might made a few mistakes in the code. As said before I copied most of this from cms/blocks. Also as stated above, the Grid doesn't load the right value but I don't know why. Anyone can tell us? :)
Good luck, Gergely
To list the selected store views in grid column add the following piece of code in grid.php in your custom module near to _filterStoreCondition() function
protected function _afterLoadCollection()
{
$this->getCollection()->walk('afterLoad');
parent::_afterLoadCollection();
}
Thanks, Sreedevi
The best example - is CMS module. You can investigate, for example, saving of CMS page.
The main table is cms_page
, and additional table is cms_page_store
.
You need to modify your entity's collection.
Take a look at Mage_Cms_Model_Mysql4_Page
class, especially _afterSave
and _afterLoad
methods.
精彩评论