「特定の国にのみ配送する」選択

※ 今回の記事はMagento CE 1.x系の管理画面について、技術者向けのお話になります。
以前、管理画面で特定出荷国を選択するとき、マルチセレクトでは選択を間違えやすいのでどうにか出来ないでしょうか。という相談をいただきました。
Magentoでは配送国を選択はマルチセレクトで配送したい国を複数選択する形式になっています。
マルチセレクトはCtrlボタンを押しながら国名をクリックする必要があるのですが、Ctrlボタンを押し忘れてクリックするとそれまでの選択が解除されてしまいます。
たくさんの国を選択しなければいけない場合や、変更をしなければいけないときに間違ってしまう可能性が高いです。
複数選択できて、一覧で見やすい。という事を考えてチェックボックスに変更することを検討してみました。
表示方法をチェックボックスに変える
管理画面での配送国設定は以下のコードで設定しています。
<specificcountry translate="label"> <label>Ship to Specific Countries</label> <frontend_type>multiselect</frontend_type> <sort_order>140</sort_order> <source_model>adminhtml/system_config_source_country</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> <can_be_empty>1</can_be_empty> </specificcountry><frontend_type>の「multiselect」部分を「checkboxes」に変えればいいのですが・・・。
変えてみたところ、チェックした項目がすべて保存されせんでした。どうやらそのままでは使えないようです。
ですので、今回はすでにあるチェックボックス機能を改造して使えるようにしてみました。
チェックボックス機能を拡張する
調べてみると、チェックボックス生成に足らないところがあるのと、保存時のデータ保持に問題があるようでした。
チェックボックス生成部分とデータ保持部分をオーバーライドしたクラスを用意します。
class Flatz_Adminhtml_Block_System_Config_Form_Element_Countries extends Varien_Data_Form_Element_Checkboxes { public function getChecked($value) { if ($checked = $this->getValue()) { } elseif ($checked = $this->getData('checked')) { } else { return ; } if (!is_array($checked)) { $checked = explode(',', strval($checked)); } if($value == 'JP'){ Mage::log($checked); } else { foreach ($checked as $k => $v) { $checked[$k] = strval($v); } } if (in_array(strval($value), $checked)) { return 'checked'; } return ; } protected function _optionToHtml($option) { // can_be_emptyの処理について、暫定対処 if($option['value'] == ''){ return; } $id = $this->getHtmlId().'_'.$this->_escape($option['value']); $html = '<li><input id="'.$id.'"'; foreach ($this->getHtmlAttributes() as $attribute) { if ($value = $this->getDataUsingMethod($attribute, $option['value'])) { $html .= ' '.$attribute.'="'.$value.'"'; } if($attribute == 'name'){ $html = substr($html, 0, -1); $html .= '[]"'; } } $html .= ' value="'.$option['value'].'" />' . ' <label for="'.$id.'">' . $option['label'] . '</label></li>' . "\n"; return $html; } }クラスを作成しただけでは管理画面での表示には使えないので、Mage_Adminhtml_Block_System_Config_Formの_getAdditionalElementTypes()をオーバーライドして <frontend_type>のタイプに追加します。今回は国の選択部分で使いたいのでcountriesという名前にしました。
public function _getAdditionalElementTypes() { $types = parent::_getAdditionalElementTypes(); $types['countries'] = Mage::getConfig()->getBlockClassName('flatz_adminhtml/system_config_form_element_countries'); return $types; }あとはオーバーライドの設定をして、管理画面設定の<frontend_type>を「multiselect」から先程設定した「countries」に変更します。
<specificcountry translate="label"> <label>Ship to Specific Countries</label> <frontend_type>countries</frontend_type> <sort_order>1910</sort_order> <source_model>adminhtml/system_config_source_country</source_model> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>0</show_in_store> <can_be_empty>1</can_be_empty> </specificcountry>キャッシュクリア後、再読込してみると

チェックボックスに変更され、保存もできました。
課題
検討段階のため、デザインや、can_be_empty(選択しないことを許可する設定)対応、デフォルト使用の場合についてまだ未対応になっています。
実際にチェックボックスに変更する場合はこれらも対応する必要があります。
まとめ
管理画面のユーザインタフェースが使いにくかった場合、このように入力欄を変更することができます。
今回はソースコードの修正が入る特殊な例でしたが、使い勝手が悪いままにするよりは変更を検討してみるとのもいいと思います。