CakePHP2.0のネーミングルールの記事翻訳


CakePHP2.0をバリバリ開発しているJose(ホセ)さんの記事をざっくり翻訳しました。自分が理解した範囲で意訳したり注釈つけてます。意味が分からない箇所は原文を参照ください。
http://bakery.cakephp.org/articles/lorenzo/2011/04/14/file_naming_and_class_loading_changes_in_cakephp_2_0
翻訳の後に自分の感想を書いてます。


事前に下記の素晴らしい記事を読んでおくと理解が深まります:)
「App::import() は凄い」




ここから翻訳
「CakePHP2.0のネーミングルール、クラスローディング」

File and folder naming, the new class loader in 2.0

CakePHP2.0ではディレクトリ構成を変えました。下記ワーキンググループで議論されている構成(PSR-0)に合わせます。
http://groups.google.com/group/php-standards/web/psr-0-final-proposal

シンプルなクラス名にしておき、ディレクトリ構成を上記のPSR-0ルールにあわせておけば、将来PHP5.3バージョンのCakePHPへの移行も楽になるのです。

今回は主要な変更箇所のハイライトをみていきましょう。

File Names

クラスが定義されている全てのファイルは名前にクラス名が入ります。1ファイル1クラスとなります。そして全て小文字かつアンダースコアが入る現在のファイル名規則は変わります。

  • my_things_controller.php は MyThingsController.php のように変わります
  • form.php (ヘルパ) は FormHelper.php のように変わります
  • session.php (コンポーネント)は SessionComponent.php のように変わります

明確になった!

Folder Names

クラスをまとめるフォルダはキャメルケース(FooBarみたいなやつ)を用いる。フォルダ名にはクラス名をいれずに、ネームスペースの階層構造をあらわす文字を入れます。

  • キャメルケースフォルダの例
    • Controller
    • Controller/Component
    • View/Helper
    • Model/Behavior

クラスを管理しないフォルダやネームスペースの一部にならないフォルダは lowercaseを用います

  • lowercased Folderの例
    • config
    • webroot
    • tmp
    • vendors

New Class Loader

新しく追加するApp::usesを使ってクラスロードを行えます。(訳者注釈: App::import()も引き続き使える)

App::uses('ClassName', 'PackageName');

php5.3のuseキーワードを連想させるメソッド名(uses)にし、クラスがどこにあるか宣言するようにします。最初の引数は読み込みたいモデル名を指定します。次の引数はパッケージ名もしくはネームスペースを指定します。
CakePHP1.3のApp::importとの違いは、App::usesの実行時にクラスは実際には読み込まれず、実際にそのクラスを利用する際に初めて読み込まれることです。

  • App::import('Controller', 'Pages') が、このように変わります App::uses('PagesController', 'Controller')
  • App::import('Component', 'Email') が、このように変わります App::uses('EmailComponent', 'Controller/Component')
  • App::import('View', 'Media') が、このように変わります App::uses('MediaView', 'View')
  • App::import('Core', 'Xml') が、このように変わります App::uses('Xml', 'Utility')
  • App::import('Datasource', 'MongoDb.MongoDbSource') が、このように変わります App::uses('MongoDbSource', 'MongoDb.Model/Datasource')

App::importでCakeコアコードを読んでいた箇所は、書き換えが必要です。そしてCoreと指定していた箇所は各パッケージに分類されているので、下記の例のようにパッケージ名の指定も必要です。

  • App::import('Core', 'CakeRoute') が、このように変わります App::uses('CakeRoute', 'Routing/Route')
  • App::import('Core', 'Sanitize') が、このように変わります App::uses('Sanitize', 'Utility')
  • App::import('Core', 'HttpSocket') が、このように変わります App::uses('HttpSocket', 'Network/Http')

CakePHP1.3のApp::importとのもう一つの違いは、App::usesは再帰的にファイル探索しません。これはデバッグモードのパフォーマンスアップに貢献します。
クラスローダは指定したパッケージのクラスのみを読み込み対象とします。

Defining package locations

App::buildはCakePHP1.3と同じように動き、フォルダの探索パスを複数指定できます。
配列のキーの名前が変わります。

  • App::build(array('controllers' => array('/full/path/to/controllers'))) が、このように変わります App::build(array('Controller' => array('/full/path/to/Controller')))
  • App::build(array('helpers' => array('/full/path/to/helpers'))) が、このように変わります App::build(array('View/Helper' => array('/full/path/to/View/Helper')))

Overriding Core Classes

Cakeのコアファイルは、Appクラス、Configureクラスを除いて、置き換え可能になります。下記にいくつかの例を示します。

  • Dispatcher classを置き換える場合は app/Lib/Routing/Dispatcher.php にファイルを設置
  • CakeRoute classを置き換える場合は app/Lib/Routing/Route/CakeRoute.php にファイルを設置
  • Model classを置き換える場合は app/Lib/Model/Model.php にファイルを設置

API changes

Appクラスの各メソッドのAPIの変更。

  • App::path($package, $plugin = null) :
    • プラグインパスもサポートするようになります。App::path('Controller', 'Users')であればUsersプラグインのコントローラのパスを返します。
    • Coreライブラリのパスは返しません。
  • App::build()
    • app pathとcore pathをマージしません
  • App::objects()
    • プラグインをサポート。App::objects('Users.Model')はUsersプラグインのモデルオブジェクトを返します。
    • 結果が空の場合は、空の配列array()を返します
    • コアオブジェクトは返しません。App::objects('core')は常に空の配列array()が返ります
    • 完全なクラス名を返します。
    • App::$componentsやApp::$modelsのようなプロパティは無くなります。
  • App::import()
    • 再帰的に探索しません。App::build()で定義された範囲で探索します(訳者注釈:app/controllers/foo/bar_controller.phpは普通には読み込まない)
    • App::import('Component', 'Component')は出来なくなるので代わりにApp::uses('Component', 'Controller')を使う
    • App::import('Lib', 'CoreClass')でコアクラスを読み込めなくなります
    • ファイルが読み込めないとか、引数の情報が足りないなどの場合はfalseを返します
    • App::import('Core', 'CoreClass')でコアクラスが読み込めなくなります。
      • App::uses('XML', 'Utils')を使って読み込む必要がある
    • vendorsディレクトリも再帰的に探索しません。
  • App::core()
    • 第1引数の指定が必須になります。
    • vendorsパスは返しません
    • App::core('Cache/Engine')といったパッケージの指定の形になります

Contents changes

  • LIBSはCakeのコアクラスが入っているフォルダを示すようになります
  • TEST_CAKE_CORE_INCLUDE_PATHは廃止します。LIBSを使ってください。


これらの変更がCakePHP2.0のパフォーマンスアップに繋がるため、みんなの開発ライフを快適にできると思ってます。


翻訳ここまで。

感想

CakePHP2.0のブランチをpullすると、ディレクトリ構造が一気に変わってビックリしました。でもこれでスッキリしたディレクトリ構成になって、「Appクラスどこやねん!あ、configure.phpの中か!」みたいなことがなくなります。将来のphp5.3 namespaceも視野に入れてるし、クラスのロードは、今までのapp::import関係のパフォーマンスに影響を与えている箇所を改善しているので、リリースが楽しみです。
後方互換に関しては、メジャーバージョンアップなので影響がありますが、そんなに大きい影響が無いようにがんばっている印象。気になる点は、App::import()が再帰的にファイルを見なくなり、Dispatcherからもコントローラの読み込みはApp::usesになっているため、今までのようにcontroller/hoge/hogehoge_controller.phpみたいにディレクトリ分けを行っていると躓きそう。事前にApp::buildをしっかり定義するステップが入るのが面倒になりそう・・・

追記

joseさんとIRCで話してたら、CakePHP2.0への移行負荷を下げるために、UpgradeShellを作ってるそうです。
https://github.com/cakephp/cakephp/blob/2.0/lib/Cake/Console/Command/UpgradeShell.php
CakePHPコアチームから感じるのは、メジャーバージョンアップであろうと、後方互換は可能な限り保ち、突っ走り過ぎないようにスピードコントロールしながらコミュニティとの距離を測ってロードマップを決めているところです。バージョンアップで過去の資産が全て無駄になるようなことを可能な限り回避しようと努力しているのが分かります。