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のときと使い方が違うので注意が必要だ。ついでに言うと、モデル内のバリデーションの記述方法にも注意が必要だ(おそらく正式バージョンリリース時までに修正されるだろう)。

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

cakePHPでファイルアップロード機能を自前で実装する

2008/03/27 | cakePHP

「自前で実装する」といってもcakeForgeのスクリプトの中で、いい感じなのを見つけたのでそれを流用するだけなのだが・・・。

以前アップロードを簡単に実現するためのコンポーネントのことを記事に書いたけど、あれはあれで複雑で自分好みにするのは少し面倒だった。であれば「コンポーネントで実現するよりもべた書きしたほうがいいかもしれない」と思い、どういうふうに記述すればいいのか探してみた。そしたらいいお手本があった。

Cheesecake Photoblog

cakeForgeのフォトアルバムを作成するためのスクリプトだ。この中のphotos_controller.php内の記述が参考になる(addの記述の部分)。

ファイルのアップロードについては、まずこんな具合に取り扱っている(その他のフォーム要素の取り扱いと同じ)。
$this->params[‘data’][‘Photo’]

で、ファイル($_FILES)の各変数を処理しないといけないわけだが、それはこんな具合にして対応できるようだ。
$this->params[‘data’][‘Photo’][‘file’]

最終的にコントローラ内では以下の一行が保存処理になっている。
$this->Photo->savePhoto($this->params[‘data’][‘Photo’][‘file’], $thumbSize, $thumbType)

つまりコントローラから、モデル(この場合はPhoto)に対して「保存処理を実行しなさい」という命令を下し、後はモデルにおまかせしてしまっているのだ。本来データの取り扱いはモデルのお仕事なのだから、これはこれで記述の仕方がスマートなように感じる。次にモデル(photo.php)のほうを見てみる。

function savePhoto($fileData,$thumbSize,$thumbType) {
  vendor(‘ccImageResize.class’);
  if (move_uploaded_file($fileData[‘tmp_name’], WWW_ROOT . “img/photos/” . $fileData[‘name’])) {
    $resizer = new ccImageResize;
    if ($resizer->resizeImage(WWW_ROOT . “img/photos/” . $fileData[‘name’], WWW_ROOT . “img/thumbnails/” . $fileData[‘name’],$thumbSize,$thumbType)) {
      return true;
    } else {
      // TODO: Clean up and set error message
      return false;
    }
  } else {
    // TODO: Set error message if move_uploaded_file fails
    return false;
  }
}

別途用意してある画像サイズ変更のためのライブラリが使用されてはいるが、直接関係のあるところは一目瞭然「move_uploaded_file」な部分だ。案外「生」なやり方で書いてある。

でもこのやり方、すごくスマートな気がするので、現在作成中のアプリはこれでいくことにする。

モデルに関係なくSQLを発行する

2008/03/26 | cakePHP

cakePHPではモデル(データベースのテーブル)とコントローラが密接に関連している。だからコントローラでデータベース内のデータを取得する際、通常は(あらかじめどのテーブルを使うか決められた)モデルを介してデータを取得するため、モデルで指定されたデータ以外を取得しようとするとエラーになったりすることがある(単にやり方がまずいだけなのだが)。
こういうときはデータベースに直接SQLを投げるのが手っ取り早い。cakePHPらしからぬ記述にはなってしまうが、個人的にはこれで十分。ノーマルな処理はcakePHPのノーマル処理に従い、一部の例外は直接SQLを発行することで進めることにした。
データベースに直接SQLを投げる方法は以下の記述を使用する。

$db=& ConnectionManager::getDataSource(‘default’);
$result=$db->query($sql);

これ、多分第二引数でキャッシュするか否かをbool値で与えるんだろうと思う(調べるの面倒なのでこのまま続行)。

SQLを書かなくてもプログラムが書けるところがcakePHPのいいところなのだが、直接SQLを書くことができるようになることで、より幅広く使えるようになるはずだ。


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