Zend_Formでのチェックボックス作成

2008/04/27 | Zend Framework

HTML_QuickForm2を使おうといろいろ試行錯誤しているが、最近Zend Frameworkに触れる機会があり(といっても自分で開発案件を抱えているわけではない)、そちらでも試してみた。

Zend Frameworkはフレームワークとして機能するのは当然だが、個々のライブラリを個別に使用することもできる非常にすばらしいツールだ。ただサンプルスクリプト自体がフレームワーク前提で記述されているようなので、お世辞にもわかりやすいとはいえない。便利なサンプル集がたくさんあるとどんどん使いたいのだが・・・。

フォームの作成はZend_Formが担当する。Zend_Formを試していて「よく考えてある!」と思ったのはチェックボックス。Zend_Form_Element_MultiCheckboxなんていうそのまんま使いたくなるようなライブラリが用意されている。もちろん複数のチェックボックスを扱うためのライブラリだ。これを使った記述方法は以下の通り。

$element=new Zend_Form_Element_MultiCheckbox(‘name’);
$element->setMultiOptions(
    array(
        ‘a’=>’A’,
        ‘b’=>’B’,
        ‘c’=>’C’,
      )
  );

これだけで配列形式で受け取ることができる複数チェックボックスを作成することができる。HTML_QuickForm2と違ういい点は値(value属性)を自由に設定できるところだ。さすがは後発フレームワーク。かゆいところに手が届いている。まだ慣れないけれど、当面ソースを追いかける努力をしてみよう。

guessworkでパラメータを自由に設定

2008/04/03 | guesswork

cakePHPも試しつつ、実は使い続けているguesswork。この軽量なフレームワークはPHP5でも動作し、いまだに手放すことができずにいる(多分使い続けるだろう)。

さて。guessworkでは外部からgetやpostで引き渡された値をcontrollerクラス内の同名のクラス変数に割り当てられるようになっている。しかし外部からの変数の汚染を防ぐために、デフォルトのクラス変数にしか割り当てられない(つまりデフォルトで想定していない引数を外部から割り当てようとしてもできない)。

これは有効なようだが、意外と使えないかもしれない。特にフォームの入力項目を可変にしたいような場合には、デフォルトでクラス変数を定義することができないので「実現不可能」ということになる(回避策はいろいろあるのだが)。

しかし本来guessworkでは、変更されたくないクラス変数は_(アンダースコア)で始めるというルールがあるわけだから、上記のような機能が不要なようだろうと思っている。もちろん想定外の変数を割り当てられてしまうというのは致命的なバグになる可能性もあるわけだから、安全をとるなら現状の記述がよいとは思う。

しかし不便だから書き換える。該当箇所はGuesswork/Controller.phpの200行目付近のinitializeController関数内の記述だ(デフォルトの状態は下記にようになっている)。

function initializeController()
{
  // call initialize method
  $method_name = “init”;
  if (method_exists($this, $method_name)) {
    call_user_func(array(&$this, $method_name));
  }

  // set acceptable form parameters to instance variable
  $vars = get_class_vars(get_class($this));
  $acceptable = array();
  foreach ($vars as $key => $value) {
    if (substr($key, 0, 1) == ‘_’) {
      continue;
    }
    $acceptable[] = $key;
  }

  // call form parameter callback if defined
  if (is_string($this->_gw_form_parameter_callback)) {
    if (method_exists($this, $this->_gw_form_parameter_callback)) {
      $this->_gw_params = call_user_func(array(&$this, $this->_gw_form_parameter_callback), $this->_gw_params);
    }
  }

  foreach ($this->_gw_params as $key => $value) {
    if (in_array($key, $acceptable)) {
      $this->$key = $value;
    }
  }

  return true;
}

この関数は3つのステージで構成されているようだ
○「// call initialize method」
 init(初期化)関数があれば実行
○「// set acceptable form parameters to instance variable」
 デフォルトの受け入れ可能なクラス変数を取得
○「// call form parameter callback if defined」
 1.外部から渡された変数群にフィルター関数をかませて
 2.受け入れ可能な変数であれば、クラス変数に代入する

「あ゛」ここでフィルターがかけられるのか。わざわざ専用関数を書いてinit関数から呼び出していたよ(後日書き直すことにする)。で最後の「受け入れ可能な変数で・・・」なところさえ書き直せば、デフォルトで変数を定義していなくても使用できるようになりそうだ。

ということで上記のプログラムの最下部を以下のように書き換えた。

  foreach ($this->_gw_params as $key => $value) {
    if (in_array($key, $vars) && substr($key,0,1)==’_’) {
      continue;
    }
    $this->$key = $value;
  }

  return true;
}

これで「外部からの変数は何でも来い」の状態になってしまっている。当面は注意するという前提で、必要に応じて関数を上書きして使用することにする。

guesswork。新しいバージョンは出ないのだろうか。だったら派生させてオリジナルクラスを作るべきだろうな。超便利だから。

cakePHP1.2はまだまだか

2008/03/31 | cakePHP

cakePHP1.2をいろいろ試してみた。その結果「まだまだ」という結論になった。現状では、素の状態で、基本機能だけを試しているのだが、それでもバグっぽい表示が出る(1.2.0.6311)。もちろんMySQLのバージョンにも依存する部分が大きいのだが、それでもやっぱりダメダメと判断した。

試したのは、bakeしたスクリプトを使ってデータの一覧・追加・修正・削除。データ削除をしようとすると、以下のエラーが出る。

(1) SQLのエラー(結果としてデータが削除できない)
Warning (512): SQL Error: 1066: Not unique table/alias: ‘Category’ [CORE/cake/libs/model/datasources/dbo_source.php, line 440]

(2) 必要なビューが作成されていない(もしくはコントローラの記述ミス)
Error: The view for CategoriesController::delete() was not found.

つまりbakeだけでは基本機能すらちゃんと動かないことになる。そもそもbakeが使えないのであれば、cakePHPを使うメリットが大きく削られるといってもいい。だからやっぱり今回は断念だ。いちおう1.2系を追っていこうとは思うが、当面は1.1系で開発するか、別のフレームワークを使うことになりそうだ。ちょっと残念・・・。

XREAでcakePHPを使う

2008/03/30 | cakePHP

最近何かと便利に使っているXREAだが、ここでcakePHPの開発を始めた。ちなみに借りているのはPHP5環境だ。自分の借りているサーバだけの問題なのかもしれないが、PHPがセーフモードらしく、cakePHPの適切なインストール手順を踏んでいくとエラーが出てしまう(realpath関数がどうとかこうとか)。なのでCGI環境で動作させてみた。インストールだけはうまくいっているようで、いつもの見慣れた画面が出てきた。今回は設定手順をメモ。

(1) 普通にcakePHPをインストール
 ファイルをアップロードして、パーミッションとかデータベース設定とか。
(2) ドキュメントルートにある.htaccessファイルの末尾に1行追加
 AddHandler application/x-httpd-phpcgi .php
(3) 以下のファイルの1行目でセッション保存場所を設定
 session_save_path(‘/PathToSessionDir/’);

これで見慣れた画面は出た(とりあえず)。この先はどうなんだろうか、と少し不安ではあるが、これで開発を進めることにする。

cakePHP1.2での確認画面

2008/03/29 | cakePHP

cakePHPでは、bakeしただけで一覧表示、追加、修正、削除の機能がすべて自動生成される。しかし追加、修正、削除の各機能では、確認画面は表示されない(同じようなことをバージョン1.1でも書いた)。バージョン1.1のときは仕方ないので自前で確認画面を実装した。もちろんその時点で、cakePHPの確認画面処理を紹介した記事があったのだが、そのときは何を自分でこだわっていたのか忘れたが自前実装したのだった(その記述はこちらを参照)。
今回は自前実装なんてばかばかしい、と思って上記のサイトをそのまま使おうと思っていたのだが・・・ところがどっこいバージョン1.2では使えなかった。いろいろ仕様が変わっているようだ。

仕方がないので、やっぱり自前で実装した。一応今回は上記の記事を参考にしつつ、なるべくcakePHPらしい記述でやることにして、以下のような内容になった(コントローラを修正)。

–[変更前]———————————————————-
function add() {
  if (!empty($this->data)) {
    $this->Site->create();
    if ($this->Site->save($this->data)) {
      $this->Session->setFlash(__(‘The Site has been saved’, true));
      $this->redirect(array(‘action’=>’index’));
    } else {
      $this->Session->setFlash(__(‘The Site could not be saved. Please, try again.’, true));
    }
  }
  $users = $this->Site->User->find(‘list’);
  $this->set(compact(‘users’));
}

–[変更後]———————————————————-
function add() {
  if (!empty($this->data)) {
    $this->Site->create();
    $btnConfirm=(isset($this->data[‘btnConfirm’])? 1:0);
    if($btnConfirm){
      $this->Site->set($this->data);
      if (!$this->Site->validates()) {
        $this->Session->setFlash(__(‘The Site could not be confirmed. Please, try again.’, true));
      }else{
        $this->Session->setFlash(__(‘The Site has been confirmed’, true));
        //$this->redirect(array(‘action’=>’index’));
        $this->render(“confirm”);
      }
    }else{
      if (!$this->Site->save($this->data)) {
        $this->Session->setFlash(__(‘The Site could not be saved. Please, try again.’, true));
      } else {
        $this->Session->setFlash(__(‘The Site has been saved’, true));
        $this->redirect(array(‘action’=>’index’));
      }
    }
  }
  $users = $this->Site->User->find(‘list’);
  $this->set(compact(‘users’));
}

なおテンプレートも修正の必要がある。やったことは以下の点。
(1) add.ctpのsubmitボタンのname属性を「data[btnConfirm]」とした
(2) 確認画面用のテンプレート「confirm.tpl」を作成した

まだ全部作りきっていないのだが、formヘルパーを使って、以下のものを組み合わせればよい。
・$form->label()
・$form->text()
・その他のtypeはそれに準じて・・・。

この作業にあたっての注意事項はモデルクラス内のvalidates()メソッドだろう。バージョン1.2は1.1のときと使い方が違うので注意が必要だ。ついでに言うと、モデル内のバリデーションの記述方法にも注意が必要だ(おそらく正式バージョンリリース時までに修正されるだろう)。

細かい記述方法は後日取りまとめてからということで。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net