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

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

WordPress高速化への道

2008/03/28 | SNS/CMS/ブログ

WordPressの便利さは大変すばらしいが、速度の遅さもすばらしい(すばらしく遅い)。もっとも・・・遅いといっても大量のデータを投稿してあれば、の話でもあるわけだが。
この遅い状況を改善する方法を考察してみた。もちろんボトルネックの洗い出しなので、WordPressよりも低次元なレベルから考えなくてはいけない。できるかできないかは別にして列挙する。

(0) インフラの高速化
WordPressが設置してあるサーバの回線環境を高速化する。もちろんレンタルサーバでは無理。一番実現できなさそうな部分ではある。

(1) ハードウェアの高速化
レンタルサーバでは無理な話。CPUの高速化はもちろんだけれど、もっとボトルネックになりそうなのがハードディスク。ストライピングを組み合わせられればかなり早くなるはず。

(2) MySQLのキャッシュ機能を利用
MySQLを適切な設定にするのはもちろんだが、キャッシュ機能を利用して、MySQLへの接続回数を減らすという方法だ。これはかなり有効だろう。しかし、この方法は専用サーバなら可能だが、レンタルサーバでは無理だ。具体的な設定箇所は「query-cache-type」や「query-cache-size」など。

(3) PHPのキャッシュ機能を利用
PHPはリクエストの都度コンパイルされる言語だ。つまりコンパイルの時間がボトルネック。だからeAcceleratorなどを組み込んでみる価値はある。もちろん専用サーバではできるが、レンタルサーバでは無理(事前に組み込まれているレンタルサーバなら問題ない)。ただし、これはアクセス数が多い場合には有効だが、そもそもアクセス数が少なければ効果が薄そうだ。

(4) WordPressのキャッシュ機能を利用
WordPressはリクエストを受けると、PHPファイルがコンパイルされ、MySQLに接続し、データを取得して表示する、という流れだ。つまりリクエストの都度MySQLに接続するので、当然MySQLが遅い場合は表示が遅くなる。だからMySQLに接続して取得したデータをキャッシュしておき、毎回データベースに接続するのをやめれば高速化が図れる。
この方法はそもそもMySQLに機能として含まれている(ただしデフォルトでは無効化されている)。この機能を有効化するには以下の作業をおこなう。
・ディレクトリ「wp-content/cache」を作成し、パーミッションは777。
・設定ファイル「wp-config.php」に以下の一行を追加(一番上がいい)。
 define(‘ENABLE_CACHE’,true);

(5) ページ単位でキャッシュする(プラグインの利用)
(4)を導入するとデータベースへの接続は減少する(無しにはならない)。しかしPHPがデータを組み立てる処理はその都度実行される。ページの組み立て作業そのものをキャッシュするのがプラグインwp-cacheだ。つまりいったん表示されたページの出力内容そのものをキャッシュしておき、次回から同じURLへのアクセスがあると、複雑な処理(データの取得やデータの組み立て)は一切スキップして、キャッシュした内容を表示するのだ。

高速化の方法は大体こんな感じ。後は不必要なプラグインは削除したり、テーマ内でのプログラム処理を極力減らすなどの努力は必要だろう。

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」な部分だ。案外「生」なやり方で書いてある。

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


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