2007年11月18日

CodeIgniterでcheckboxを作ってみる

前回までで検索フィールド×3、表示件数変更ドロップダウンメニュー、検索結果のページングを実装した、なんちゃって検索アプリ風味(謎)なモノができあがりました。前回と前々回は多少詰め込みすぎた?というかBlogが若干長めになってしまいましたが、これには一応わけがあって、実は前回までで実際に作っている(手続き型スクリプトをCodeIgniterで書き直している)プログラムにBlogが追いついたのです。

なので今回からはネタにしているこのサンプルプログラム的には新機能の追加ということになります。新機能といっても、大元の(本来こっちをとっととCodeIgniterで書き直したい謎の)スクリプトには実装されているようなごく一般的なもので、CodeIgniterで書くにはどうしたらいいだろう?といったことを、今回からはスクリプト作成と平行してBlogに綴っていく予定です。

ということで今回はcheckboxです。DropDownFieldと同じくGUI部品だけ作ってもアレなんで、今回は表示モード?を切替えてみたいとおもいます。

これまでは都道府県・新市町村・旧市町村・合併日というカラムのテーブルを表示していましたが、新たに新市町村・合併日だけのカラムにした簡易表示?みたいなモノを出力することにして、それと通常表示?詳細表示(つまり今までの表示ですが)を切替える機能を加えます。

表示イメージ
disp_simple.png
まあこの表示がユーザにとって必要かどうかということはさておき(サンプルですから)、とにかくやりたいことは、表示状態?をcheckboxで切替えるってことです(^^;

そこでまず「表示」ということで前回の表示件数変更を切替えた際のformを利用しようと考えました。利用というか同じformにcheckbox作って、検索条件をセッションに格納した時と同じように配列にしてcookieに入れて…と考え実際に書いてみましたが、結論から言うとそのやり方では二重に失敗?しました(--;

失敗した経緯を詳しく書こうともおもったのですが、無駄に長くなるので、どこがダメだったかだけメモしておきます。

まずセッションで配列を格納する際にはserialize()を使っていましたが、cookieではこれがどうもうまく機能しなかったのです。具体的にはpost配列をserialize化することは強引に?できるみたいなのですが、それを読み出す時点で、もちろんunserialize()を使いますが、何故かうまくいきませんでした。

またPHPのマニュアルによると…
クッキー名で配列を記述することにより、 クッキーの配列を設定することも可能ですが、複数のクッキー がユーザーのシステム上に保存されることになります。 explode() を使用して ひとつのクッキー上に複数の名前と値をセットすることも 考慮してください。serialize() の使用はセキュリティーホールになり得るため、 この目的のために使用することは推奨されません。

ということなので、いずれにしろserializeは却下されました。

そして単独で、つまり表示件数の数値とは別に、cookieに保存してやればまあいいだろうとおもい、そのようなコードを書いたのですが、今度はcheckbox特有の動作によってうまくいきませんでした(--;。

この「checkbox特有の動作」はおそらくwebのプログラムを書いた人は一度はハマルんではないかとおもいますが、要するに…
checkboxがチェックされていないときはpostデータが送られてこない

という仕様のことです。

もう少し具体的にいえば、例えばテキストフィールドの場合だと<input type="text" name="hoge"〜のようになっていれば例え入力が空でも$_POST['hoge']という変数自体は存在するわけですが、これがチェックボックスだと<input type="checkbox" name="hage"〜のようになっていても、チェックされていない場合は$_POST['hage']という変数自体がないわけです。

なので不用意に if ($_POST['hage'] == TRUE)〜のようなコードを書いてしまうと、そもそも$_POST['hage']がないので、hageって何?みたいなエラーになってしまうわけです。

そして性質が悪い?というかやっかいなのは、↑のようになる場合はあくまでもチェックが外された状態でサブミットされた時であって、チェックを付けてサブミットされた時は何の問題もなかったかのように動いてしまったりすることです。

チェックボックスのこのような挙動は一見不合理なように見えますが、実は複数のチェックボックスをラジオボタン的に使う場合などは便利かもしれません。ラジオボタンだとどれか一つは必ず選択状態になりますが、チェックボックスだとどれも選択しないということができるからです。

ただ今回の場合のように単に真偽値だけを受取りたい場合は、その他のform部品とはちょっと違った挙動だということを考慮しないと、はまる原因になったりします。(ってか実際はまってます)

というわけで冗長的な感がないでもありませんが、メソッドを一つ作ることにして、前回の表示件数とは別に処理するような形にしました。またViewをヘッダ部・フォーム部・メイン部・フッタ部に分けて、共通部分はView内で別のViewを呼び出す形にし、新たにメイン部を2つ作りそれを切替えるようにControllerに記述しました。

View
<?$this->load->view('header');?>
<?$this->load->view('form');?>
<hr>
<?if($count > 0):?>
※この部分でデータをテーブルタグで出力
※gappei_detail.phpとgappei_simple.phpの2通りのViewを作成
<?else:?>
<p>該当データがありませんでした。</p>
<?endif;?>
<hr>
<?=$pagination?>
<?$this->load->view('footer');?>


Controller
function changeDispMode()
{
set_cookie('dispmode', $this->input->post('dispmode'), Gappei::COOKIE_LIFE);
redirect('gappei/index/');
}

結果的にchangeDispNumber()とほとんど同じになっていますが、挙動はかなり違います。ポイントは$_POST['dispmode']を直接受取らないで、CodeIgniterのライブラリ経由にすることで変数が存在しなくても(チェックが外されてpostされた場合)エラーにはならないという部分です。さらに(チェックが外されてpostされた場合は)空のデータをcookieにセットしているので、cookie自体が消去されます。つまりtureとかfalseとかの値がdispmodeというcookieに格納されるのではなく、falseの場合はそもそもcookieが削除されるということです。
//表示モード取得
$data['dmChecked'] = (get_cookie('dispmode') <> '') ? get_cookie('dispmode') : FALSE;

//表示viewロード
if ($data['dmChecked'] == TRUE)
{
$this->load->view('gappei_detail', $data);
} else {
$this->load->view('gappei_simple', $data);
}
ラベル:codeigniter
posted by ciallost at 15:02| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック