CodeZine(コードジン)

特集ページ一覧

CakePHP内の処理を理解する

PHPフレームワークの処理の流れを追う

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/12/18 00:00

目次

2.include_pathの技法

 相対パスを使ってincluderequireを実行するようにしていると、「includeが書いてあるファイルを別な階層のディレクトリからincludeしようとする際、エラーになってしまう」ということがあります。フレームワークでは複数のディレクトリから、いくつかのファイルを読み込むことになるので、このあたりが悩ましいのですが、CakePHPではinclude_pathを後から設定することでこの問題を解決しています。

 Cakeは単に圧縮ファイルを展開して配置するだけで、開発が始められるように設計されています。しかし開発が終わって実運用する際に、「webroot」フォルダだけをWEBに公開する、という配置にすることも考慮されています。サーバのDocumentRootの変更権限を持っている場合には、CakePHPのディレクトリ構成を変えずに、単にDocumentRootの位置を「app/webroot」ディレクトリに設定するだけでCakePHPアプリケーションを動かすことができます。これがいちばん簡単な公開用のセッティングです。

 しかし、さらに高度に設定を変える方法もあります。関係するパラメータは、ROOTAPP_DIRCAKE_CORE_INCLUDE_PATHです。

  1. Cake本体
  2. CAKE_CORE_INCLUDE_PATH Cakeの本体が入っている「/Cakeインストールフォルダ/Cake本体」の位置を設定します(デフォルトでは、ROOTと同じパスが入っています)。Cakeライブラリディレクトリの「ひとつ上の階層」を指定することに注意しましょう。
  3. 自分の作成したプロジェクトファイル
  4. ROOT ここで言うROOTとは、「cake/appフォルダ」が入っているディレクトリを指します。データベースの設定ファイル、自分の書いたモデル、コントローラ、ビューファイルなどの一式の入ったディレクトリを指定します。
    APP_DIR このAPP_DIRには、「ディレクトリの名前」が入ります(デフォルトは、「app」です)。具体的には、「ROOT.DS.APP_DIR」という形で使用されることになります。
  5. 公開する「webroot」ディレクトリ
  6. 公開する「webroot」に関してですが、全部が公開されている場合には、htaccessのRewriteRuleによって「app/webroot」に自動的に飛びます。また、「app/webroot」部分だけが公開されている場合には、そこにユーザが直接見に行くので、「webroot」フォルダのパスを指定する必要はありません。

 これで、

  1. Cake本体
  2. 自分の作成したプロジェクトファイル
  3. 公開する「webroot」ディレクトリ

 の3つが決まることになります。

WEBROOT_DIRとWWW_ROOT
 マニュアルには書かれていませんが、設定にかかわる定数には、
 WEBROOT_DIR:WEBROOTに相当するディレクトリの名前(デフォルトは「webroot」)。
 WWW_ROOT:WEBROOT_DIRがある場所へのパス
 もあります。
 「mod_rewrite」が効いていたり、「app/webroot/index.php」に直接たどりついたりした場合には、自動的に上の2つの定数の値が設定されます(「app/webroot/index.php」のファイルがある位置が、WWW_ROOT+WEBROOT_DIRということです)。しかし、「mod_rewrite」が効かない状態でcakeの親フォルダからアクセスさせ、webrootの位置も変更したい場合には、この値を自分で設定する必要があります(現在の「index.php」の設定は、単純にCakePHPプロジェクトを展開した場合に正しく動くようなパス設定になっています)。

index.php

 CakePHPの内部を理解するために、index.phpのコードを少したどってみます。

app/webroot/index.php
if (!defined('CORE_PATH')) {
    if (function_exists('ini_set')) {
        ini_set('include_path', ini_get('include_path')
        .PATH_SEPARATOR.CAKE_CORE_INCLUDE_PATH
        .PATH_SEPARATOR.ROOT.DS.APP_DIR.DS);
        define('APP_PATH', null);
        define('CORE_PATH', null);
    } else {
        define('APP_PATH', ROOT.DS.APP_DIR.DS);
        define('CORE_PATH', CAKE_CORE_INCLUDE_PATH.DS);
    }
}
require CORE_PATH.'cake'.DS.'bootstrap.php';

 ここで、設定オプションが追加できることを確認してから、include_pathの中に、CakeのCAKE_CORE_INCLUDE_PATHのパスとROOT+APP_DIRのパスを追加しています(PATH_SEPARATORは、Windowsの場合はセミコロンになることに注意)。さらに、APP_PATHCORE_PATHという定数はnullに設定されるので、これは存在していないことと同じになります。

 ですから、次の

require CORE_PATH.'cake'.DS.'bootstrap.php';

 という部分は、

require 'cake/bootstrap.php';

 として呼んでいるのと同じことになります。include_pathが使えない環境であれば、この部分は、

require 'Cakeのcoreがインストールされたパス/cake/bootstrap.php';

 として実行されます。独自にCAKEファイルをrequireするときには、APP_PATHCORE_PATHの定数を含めておくようにしましょう。そうすれば、ディレクトリの階層を考える必要がありません。しかし、たいていの場合はnullになっており、実際のパスはinclude_pathに記述されている場合がほとんどでしょう。

CakePHPのクラスや各メソッドは、APIマニュアルで調査できます。
CakePHPのクラスや各メソッドは、APIマニュアルで調査できます。

3.PHPのバージョンによる使い分け

 CakePHPはPHP4とPHP5をサポートするフレームワークです。そのため、PHP5の環境で開発し、クライアントの要望に応じて、PHP4のサーバにしたり、PHP5で運用したりと使い分けることが可能です。しかし、PHP4とPHP5でどんな違いがあるのかを開発者が把握している必要があります。CakePHPフレームワークにかかわってくるPHP4とPHP5の大きな違いは、

  • PHP5のデフォルトでは、オブジェクトのコピー方法が参照渡しになった
  • PHP4では、コンストラクタ名はクラス名と同じ関数。PHP5では__constructというメソッドが優先される
  • メンバーとメソッドのオーバーロード

 などがあります。CakePHPはこの3つの違いを吸収するために次のような処理を行っています。

  1. 「model_php4.php」と「model_php5.php」という2つのModelクラスを準備し、model.php内の下記のコードで読み分ける。
  2. if (phpversion() < 5) {
        require(LIBS.'model'.DS.'model_php4.php');
    
        if (function_exists("overload")) {
            overload("Model");
        }
    } else {
        require(LIBS.'model'.DS.'model_php5.php');
    }
    
  3. すべてのクラスをobject.phpから派生させます。そして、Objectクラスのコンストラクタで下記のような作業を行います。
  4. function Object() {
        $args = func_get_args();
        if (method_exists($this, '__destruct')) {
            register_shutdown_function (array(&$this, '__destruct'));
        }
        call_user_func_array(array(&$this, '__construct'), $args);
    }
    
    register_shutdown_function()は、スクリプト処理が完了した際に実行される関数を登録します。これで__destruct()をPHP4でも定義できるようにします。また、__constructというメソッドを、call_user_func_array()で呼び出します。派生したクラスで__constructが定義されると、PHP4でもそれが呼ばれるようになります。派生クラスの__construct内では、parent::__construct();を呼ぶようにします。
  5. CakePHPのモデルには、findAllByフィールド名($value);というマジック関数があります。これは、例えばあるusersテーブルの中に、titlenameaddressがある場合には、
  6. $this->User->findByTitle('CakePHPとajax');
    $this->User->findByName('phpnut');
    $this->User->findByAddress('東京都');
    
    などのような仕方で検索できるようになります。この処理は、オーバーロードという機能で実現されています。PHP5の機能として主に紹介されますが、実験的にPHP4でもこの機能が使えるようになっています。しかし、PHP4.3.2で、overload拡張モジュールでメモリが破壊されるバグが修正されたので、overload()関数がきちんと使えるのはそれ以降のバージョンです。CakePHPの環境要件がPHP4.3.2以上となっているのはこれが理由です。「model_php4.php」と「model_php5.phpの」__call()と、「libs/model/datasources/dbo_source.php」のquery()関数を読んでみると、どのようにしてこの処理が実現されているかを見ることができます。関心のある方は研究してください。

まとめ

 フレームワークの利用は、人を雇って作業をしてもらうのに似ています。開発者が書く必要のあるコードが減り、セキュリティや各DBの違いなどこまごまとしした部分の作業はフレームワークが面倒をみてくれますので開発効率は驚くほど向上します。その一方で、自分には覚えのないバグが入る可能性も否めません(多くの人が使っているフレームワークであれば、大半の部分が徹底的にテストされ、改善されていきますが……)。そんな時、フレームワークの動作の仕組みを理解していると、解決までの時間が短縮されるはずです。フレームワークを上手に使って、どんなWEBアプリケーション開発案件にも笑顔で対応できる、そんな開発チームになりたいものですね。

bakery.cakephp.orgには読者から投稿された記事が多数掲載されています。
bakery.cakephp.orgには読者から投稿された記事が多数掲載されています。


  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:CakePHPチュートリアル

著者プロフィール

  • 堂園 俊郎(ドウゾノ シュンロウ)

    (株)コミュニケーション・ビジネス・アヴェニュー技術担当。著書「CakePHPガイドブック」。CentOSサーバによる大小のコールセンター立ち上げ業務のかたわら、オープンソースプロダクトのコンサルティングを行う日々。http://cakephp.jpの管理人。ブログ:「CakePHPのおいしい食べ方...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5