add to hatena hatena.comment (2) add to del.icio.us (0) add to livedoor.clip (0) add to Yahoo!Bookmark (0) Total: 2

CakePHP Formヘルパの拡張 その2
3項目の電話番号入力フィールド

$form->textを拡張して3項目の電話番号入力フィールドを生成

前回に続いて、Formヘルパの拡張の第二弾です。
入力欄としてよくあるものとしては、電話番号や郵便番号を分割された入力フィールドで入力させるケースがあります。
入力フォームはモデル(テーブル)と連携するケースが多いですが、テーブルのカラムが1つなのに入力フォームは分割しなければならない場合などは、少々面倒なことを行う必要があります。

この煩わしさを回避する為に、カラムは1つでも入力欄は3つに自動的に分割されるようにに拡張する方法を検討しました。

結論から言えば、ヘルパだけの拡張では入力欄を分割するところまではできましたが、DBに格納する際に自動的に分割した値を結合することができませんでした。
(イマイチな)解決案として、AppModel内に処理を追加することでDB格納時の自動結合化を行っています。
動作はこちらから確認できます。

準備

前回利用したExformヘルパ(exform.php)のソースにtel()メソッドを追加します。

PHP:
  1. // 3項目の電話番号フィールド
  2.     function tel($fieldName, $options = array()) {
  3.         $defaults = array(
  4.             'separator' => ' - ',
  5.         );
  6.         $options = array_merge($defaults, (array) $options);
  7.         $separator = $options['separator'];
  8.         unset($options['separator']);
  9.        
  10.         $value = $this->value($fieldName);
  11.         if(is_array($value)){
  12.             $vals = $value;
  13.         }else{
  14.             $split = explode('-', $value);
  15.             $vals['_1'] = (isset($split[0])) ? $split[0]:'';
  16.             $vals['_2'] = (isset($split[1])) ? $split[1]:'';
  17.             $vals['_3'] = (isset($split[2])) ? $split[2]:'';
  18.         }
  19.        
  20.         $tels = array();
  21.         $tels['_1'] = $this->text($fieldName.'._1', am($options, array('value'=>$vals['_1'])));
  22.         $tels['_2'] = $this->text($fieldName.'._2', am($options, array('value'=>$vals['_2'])));
  23.         $tels['_3'] = $this->text($fieldName.'._3', am($options, array('value'=>$vals['_3'])));
  24.        
  25.         return implode($separator, $tels);
  26.     }

このファイルを
app/views/helpers
に配置。
コントローラーの先頭のヘルパ定義時に、標準のFormヘルパとセットで呼び出します。
(前回同様です)

PHP:
  1. var $helpers = array('Form','Exform');

AppModel(または各モデル)に処理を追加

$form->datetime() などは入力項目を分割しているにも関わらず、
$model->save()時には正しくデータを連結して保存されていました。
この部分を解析するとコアのmodelクラス内で以下のメソッドにより処理されていることがわかりました。
このままでは、いくらヘルパで拡張しても保存時にエラーになってしまいますので、
今回はapp_model.phpにこのメソッドをオーバーライドする形で対応します。

app/app_model.php にメソッドを追加

PHP:
  1. /**
  2.      *  セット時の配列形式の結合を拡張
  3.      */
  4.     function deconstruct($field, $data) {
  5.         $retData = parent::deconstruct($field, $data);
  6.         // 分割された電話番号データをハイフンで連結する場合
  7.         if(!is_numeric($field) && is_array($retData) && Set::countDim($retData) == 1){
  8.             // 誤作動防止の為、電話番号カラムを指定する
  9.             if(in_array($field, array('tel', 'fax', 'phone'))){
  10.                 $retData = implode('-', $retData);
  11.                 $retData = trim($retData, '-');
  12.             }
  13.         }
  14.         return $retData;
  15.     }

※全ての配列データが処理されると問題が起こる可能性がありますので、'tel', 'fax', 'phone'というカラムのみデータが配列だったら、ハイフンで連結する処理を加えています

実装方法

ビューの中で

PHP:
  1. <?php echo $exform->tel('カラム名', オプション配列); ?>
  2.  
  3. // 例
  4. <?php echo $exform->tel('phone', array('style'=>'width:60px', 'separator'=>'-')); ?>

として利用します。

※オプション配列は通常の$form->text()のものに表示の際の分割文字列パラメータ(separator)を追加しています。

関連するその他の記事

Comments

Leave a Reply