まず第一に...素敵な質問。本当に興味を持ってもらいました。
カスタムレンダラー(テンプレート)を持つ属性を作成し、値をシリアル化して保存する方法の例を次に示します。
この例では、2つのテキスト入力を持つ属性を作成しましたが、基本的にはそこに何でも置くことができます。
属性を処理するカスタムモジュールを作成することをお勧めします。この拡張機能を呼び出しましょうEasylife_Attr
。
以下のファイルが必要です。
app/etc/module/Easylife_Attr.xml
-宣言ファイル。
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Attr>
<codePool>local</codePool>
<active>true</active>
<depends>
<Mage_Catalog /><!-- should depend on mage_catalog-->
<Mage_Adminhtml /><!-- should depend on mage_adminhtml-->
</depends>
</Easylife_Attr>
</modules>
</config>
app/code/local/Easylife/Attr/etc/config.xml
-構成ファイル
<?xml version="1.0"?>
<config>
<modules>
<Easylife_Attr>
<version>0.0.1</version>
</Easylife_Attr>
</modules>
<global>
<resources>
<easylife_attr_setup>
<setup>
<module>Easylife_Attr</module>
<class>Mage_Catalog_Model_Resource_Setup</class><!-- use the catalog setup so you can add your attribute -->
</setup>
</easylife_attr_setup>
</resources>
<models>
<easylife_attr>
<class>Easylife_Attr_Model</class>
</easylife_attr>
</models>
<blocks>
<easylife_attr>
<class>Easylife_Attr_Block</class>
</easylife_attr>
</blocks>
</global>
<adminhtml>
<events>
<adminhtml_catalog_product_edit_prepare_form><!-- event needed to add a template to a certain attribute -->
<observers>
<easylife>
<class>Easylife_Attr_Model_Observer</class>
<method>convertCustomValues</method>
</easylife>
</observers>
</adminhtml_catalog_product_edit_prepare_form>
</events>
</adminhtml>
</config>
app/code/local/Easylife/Attr/sql/easylife_attr_setup/install-0.0.1.php
-インストールスクリプト。それはあなたの属性を追加します
<?php
$this->addAttribute('catalog_product', 'custom_values', array(
'group' => 'Custom values', //the tab name where the attribute will be placed
'input' => 'textarea', //this is not really important
'type' => 'text', //attribute type should be text to support long values
'label' => 'Custom values', //the attribute label
'backend' => 'easylife_attr/custom', //a custom backend model that will handle serialization and deserialization
'visible' => true,
'required' => false,
'visible_on_front' => true,
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL, //scope can be anything but if it's not global you will need some changes to support store view values
));
楽しい部分です。
app/code/local/Easylife/Attr/Model/Observer.php
-属性テンプレートを変更するオブザーブ
<?php
class Easylife_Attr_Model_Observer {
public function convertCustomValues($observer) {
$form = $observer->getEvent()->getForm();
$customValues = $form->getElement('custom_values');
if ($customValues) {
$customValues->setRenderer(
Mage::app()->getLayout()->createBlock('easylife_attr/adminhtml_product_custom')
); //set a custom renderer to your attribute
}
}
}
app/code/local/Easylife/Attr/Block/Adminhtml/Product/Custom.php
-カスタムレンダラーブロック
<?php
class Easylife_Attr_Block_Adminhtml_Product_Custom
extends Mage_Adminhtml_Block_Widget
implements Varien_Data_Form_Element_Renderer_Interface {
public function __construct()
{
$this->setTemplate('easylife_attr/product/custom.phtml'); //set a template
}
public function render(Varien_Data_Form_Element_Abstract $element) {
$this->setElement($element);
return $this->toHtml();
}
}
app/design/adminhtml/default/default/template/easylife_attr/product/custom.phtml
-属性のテンプレート。
<?php
$_htmlId = $this->getElement()->getHtmlId();
$_htmlClass = $this->getElement()->getClass();
$_htmlName = $this->getElement()->getName();
$_readonly = $this->getElement()->getReadonly();
$value = $this->getElement()->getValue();
//get the values for the 2 text elements
$someField = (isset($value['some_field']) ? $value['some_field'] : '');
$otherField = (isset($value['other_field']) ? $value['other_field'] : '');
?>
<tr> <!-- should be wrapped in a tr element to fit in the admin template -->
<td class="label"><?php echo $this->getElement()->getLabel(); ?></td>
<td colspan="10" class="grid">
<table cellspacing="0" class="data border">
<col width="120" />
<col />
<thead>
<tr class="headings">
<th><?php echo $this->__('Some field')?></th>
<th><?php echo $this->__('Other Field')?></th>
</tr>
</thead>
<tbody id="<?php echo $_htmlId; ?>_container"></tbody>
<tfoot>
<tr>
<td><input type="text" name="<?php echo $_htmlName; ?>[some_field]" value="<?php echo $someField?>"<?php echo ($_readonly) ? ' readonly="readonly"' : ''?>> </td>
<td><input type="text" name="<?php echo $_htmlName; ?>[other_field]" value="<?php echo $otherField?>"<?php echo ($_readonly) ? ' readonly="readonly"' : ''?>></td>
</tr>
</tfoot>
</table>
</td>
</tr>
app/code/local/Easylife/Attr/Model/Custom.php
-シリアライゼーションとデシリアライゼーションを処理するモデル。
<?php
class Easylife_Attr_Model_Custom extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract{
public function beforeSave($object)
{
//before sabing the product check if the attribute `custom_values` is array.
//if it is, serialize it for saving in the db
$attributeCode = $this->getAttribute()->getAttributeCode();
$data = $object->getData($attributeCode);
if (is_array($data)) {
$data = array_filter($data);
$object->setData($attributeCode, serialize($data));
}
return parent::beforeSave($object);
}
public function afterLoad($object) {
//after loading the product, check if the value for custom_values is not an array. If it's not try to unserialize the value.
$attributeCode = $this->getAttribute()->getAttributeCode();
$data = $object->getData($attributeCode);
if (!is_array($data)) {
$object->setData($attributeCode, @unserialize($data));
}
return parent::afterLoad($object);
}
}
それでおしまい。次に、属性がバックエンドでどのように見えるかを示します。