10月 132012
 

おはようございます。ファガイです。
今日は、Fieldsetクラスをまとめる予定でしたが、時間も無かったのでFieldsetクラスのバグの対処方法を模索しておりました。

まず、そのバグについてです。

$form = Fieldset::forge('form');
$form->add('sex', '性別', array('type'=>'radio', options=> array(1=>'男性',2=>'女性),'value'=>1));
$form->build();

上記のようなコードを書いた際、

<input type="radio" value="1" id="form_sex_0" name="sex" checked="checked" /> <label for="form_form_sex_0">男性</label><br />

<input type="radio" value="2" id="form_sex_1" name="sex" /> <label for="form_form_sex_1">女性</label><br />

このようなコードが生成されるかと思います。

で、問題点は、labelのforの部分。forの値が対応しているラジオボタンのidと一致せず、文字をクリックしてもチェックが入らない形になります。

ソースコードを確認したところ、どうやら内部でまずauto_id_prefixをフィールド名につけた後、attlibutes連想配列内にidという名前で格納している模様。そしてそれを利用して各Formクラスからのinputタグ等が生成されているようです。

そのため、変更するところは、/core/form/instance.phpとなります。

対処法

2012/10/18追記
はじめてのフレームワークとしてのFuelPHPで有名な@kenji_sさんが、このバグの報告をしてくださっていました。それも結構前からしてくださっていたようです。(6月?でした・・・w)
Fieldset Field Label “for” does not match Input “id”

そちらに基づくと、classes/fieldset/field.phpのbuild関数の部分を一部変更。

{
  $attributes = $this->attributes;
  $attributes['name'] = $this->name;
 -$this->type == 'checkbox' and $attributes['name'] .= '['.$i.']';
  $attributes['value'] = $value;
  $attributes['label'] = $label;    

...  ...    

  $attributes['id'] = null;
}
-$build_field[$form->label($label, $attributes['id'])] = $this->type == 'radio'
+$build_field[$form->label($label, $attributes['name'].'_'.$i)] = $this->type == 'radio'
 ? $form->radio($attributes)
 : $form->checkbox($attributes);

+が追加で-が削除行です。
これで治るのですが、しっかり内容の理解が出来なかったのでソース確認が必要ですね。誰か教えてくれると助かります。


まず、580行目付近にあるlabelメソッドを探す

if (empty($attributes['for']) and $this->get_config('auto_id', false) == true)
{ 
    $attributes['for'] = $this->get_config('auto_id_prefix', 'form_').$id;
}

この部分を、こうします。

if (empty($attributes['for']) and $this->get_config('auto_id', false) == true)
{
$auto_id = $this->get_config('auto_id_prefix', false);
if($auto_id !== false)
{
    if(strpos($id, $auto_id) !== false) 
    {
        $attributes['for'] = $id;
    }
    else
    {
        $attributes['for'] = $this->get_config('auto_id_prefix', 'form_').$id;
    }
}

これでOK。
ただこの注意点としては、auto_prefixの文字列をフィールド名に使えないことぐらいでしょうか。
form_という名前を使いたい時は個別でconfigファイルを作ってauto_id_prefixの名前を変更することで対処できます。

APPPATH/config/form.php

<?php
return array(
    'auto_id_prefix' => 'この部分を変更',
);

このようにすることで対処ができます。現状ではこれで問題無さそうなのですが何かおかしかったらコメントください。

追記
ちなみに、core内を変更しなくてもauto_id_prefixを無くしても対処が可能です。しかしながら、id名がHTML内で重複する可能性があるためこのようにしました。どうしても中身を変更したくない場合はこちらでもいいでしょう。

追記2
どうやらこの場合はauto_id_prefixを指定しなかった場合、forがつかない気がする・・・。if($auto_id !==false)にelse文をつけて、そこにも$attributes[‘for’] = $this->get_config(‘auto_id_prefix’, ‘form_’).$id;を書かなくてはいけない気がしてきました。

Pocket

 Posted by at 9:39 AM

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*