DotCloud で PHP アプリを設置してみたときの色々
beta の invite もらったので DotCloud で遊んでみました。
アプリ1つくらい設置してみないとなんだかよくわからないよねってことで、とりあえずどこで公開するかなーと思っていた、paste アプリ を設置してみた。
- Pastit: http://www.pastit.dotcloud.com/
- Pastit GitHub: https://github.com/sotarok/pastit/
DotCloud の PHP の環境は、Ubuntu 上の nginx + php5-fpm (PHP 5.3.2) が標準で、なんというか時代の流れを感じました。いいね!
のは、まあいいとして、まぁ PHP アプリなんてものはたいてい Apache で動くことが前提とされてるもので (そうなのか? いや、そうだと思う。それが PHP のメリットだし) nginx な環境とか全然考慮してなかった + そんな PHP ユーザな弊害として nginx 力が低すぎてアレだったのですこしばかりはまったので、まあそのあたりのメモとして。
ということで、話は Pastit のディレクトリ構成を前提に進めますが、GitHub にあがってるので参考にしてください。
主な話の内容は、
- DotCloud のアプリ設置操作
- DotCloud の環境とか
- DotCloud + PHP + nginx の環境とか
とりあえず設定
まあ Tutorial で言われてるとおりコマンドをインストールして、アプリケーションサーバと MySQLサーバをつくってみる。
最初に dotcloud コマンドを使ったときに token をセットしろっていわれるけどこれはログインして setting を見たときに書いてあるやつな。
$ dotcloud list $ dotcloud create pastit $ dotcloud deploy --type php pastit.www $ dotcloud deploy --type mysql pastit.mysql
MySQL の設定とかは以下で確認
$ dotcloud info pastit.mysql cluster: wolverine config: mysql_password: **** created_at: 1304535584.4373901 name: pastit.mysql namespace: pastit ports: - name: mysql url: mysql://root:****@mysql.pastit.dotcloud.com:port - name: ssh url: ssh://dotcloud@mysql.pastit.dotcloud.com:port state: running type: mysql
MySQL は、以下でログインできるので、これでログインして DB 作ったりユーザ作ったりする。
$ dotcloud run pastit.mysql -- mysql -uroot -p\'****\'
で、ソースコードのデプロイ。今回は Git リポジトリです。Pastitのリポジトリのルートで実行。Gitのブランチを指定する場合は -b で。しなければ master が push される。
$ dotcloud push -b develop pastit.www .
で、http://www.pastit.dotcloud.com/ で動けばOK。今回は pastit.www という名前でデプロイしてるからこのURLになるけど、pastit.* に当たる部分が URL のサブドメイン *.pastit.dotcloud.com になる。
前提として知っておくべき DotColud の環境
push するとなにがどう設置されるか
DotCloud に push すると、以下のようなディレクトリ構成で設置される。とりあえず type = PHP の場合の話だが、アプリケーションサーバの場合他のタイプでも大差ないだろう。
dotcloud@pastit-www:~$ pwd /home/dotcloud dotcloud@pastit-www:~$ ls -la -rw-r--r-- 1 dotcloud www-data 54722 2011-05-06 18:53 build.log drwxr-xr-x 13 dotcloud www-data 4096 2011-05-06 18:53 c1bda3a lrwxrwxrwx 1 root root 7 2011-05-06 18:53 code -> c1bda3a lrwxrwxrwx 1 dotcloud www-data 8 2011-05-06 18:53 current -> code/www
この c1bda3a ってやつがコードの実態。
今回の場合リポジトリが Git だったので Git でのデプロイした時のコミットオブジェクトの hash 値になっている。
code ってやつは、常に最新のソースのルートへの symlink になっている。
current ってやつも symlink で、ここがアプリケーションの root (ドキュメントルート的な) の場所を指し示す。ここは、特に何も設定しなければ、 code と同じ場所を指すが、次に説明する dotcloud_build.yml で設定することで変更できる。
capistrano とかを使ったことがあれば、ソースコードが配置されて、最新のツリーへの symlink があって、みたいな構成はだいたい同じなのでキャッチアップしやすいと思う。
dotcloud_build.yml
DotCloud にアプリを push をすると、そのディレクトリをドキュメントルート *1 として設置される。多くのフレームワークのアプリの場合これは好ましくないはず。
なので、そのへんを設定してあげるのが docloud_build.yml。ここに、アプリの root がどこなのかという設定を記述できる (その他の設定項目もあるがとりあえずは省略) 。
このファイルは push するディレクトリのルートにおいておく。今回は approot として www ディレクトリを指定。
www: approot: www
nginx.conf と fastcgi.conf
approot 以下においておくと、読み込んでくれる nginx の設定。
といっても、Apache の .htaccess とはちがって、単に nginx の設定で include されてるだけだから、pushしたときに nginx が reload されてはじめて設定は適用される。
両者の違いは、
というだけ。これは設定が include される場所が違うだけ。PHP に関する設定は fastcgi.conf にしておくのがよさそう。
nginx.conf と fastcgi.conf は、deny 設定されてたのに、次に説明する postinstall だけ deny されてなかったので、それを nginx.conf に書いておいた。あと try_files の設定 (後述)。
try_files $uri $uri/ /index.php?$args; location = /postinstall { deny all; }
postinstall
いかにも Debian 好きっぽそうなこの名前は、approot 以下に実行ファイルとしておいておくと、push の最後に実行してくれる。アプリケーションの設定の適用を行うファイルとかを適切においておけば良い。
ちなみに、Pastit は Ethna の config を home においておいて、それを push 時に適切なディレクトリにコピーするようにしている。PHP厨らしくちゃんとPHPで記述しておく。
#!/usr/bin/php <?php define('DOTCLOUD_HOME', '/home/dotcloud/'); $files = array( 'pastit-ini.php' => 'code/config/pastit-ini.php', 'pastit-app-ini.php' => 'code/config/pastit-app-ini.php', ); foreach ($files as $origin_file => $dest_file) { if (!file_exists(DOTCLOUD_HOME . $dest_file) && file_exists(DOTCLOUD_HOME . $origin_file)) { echo DOTCLOUD_HOME . $origin_file, " -> ", DOTCLOUD_HOME . $dest_file, PHP_EOL; copy(DOTCLOUD_HOME . $origin_file, DOTCLOUD_HOME . $dest_file); } } // task echo 'end of task', PHP_EOL;
その他
まあ ssh で入って /etc/nginx 以下をのぞけばわかることだけど、
- favicon.ico は current/static/favicon.ico (approot/static/favicon.ico) を参照される
- robots.txt も current/static/robots.txt を参照される
nginx x PHP な設定
PAHT_INFO とか
PATH_INFO使ってる人ってどれだけいるのかわからないけど Ethna の UrlHandler はそれ使って path 解析するから、あるといい。
んだけど、PHP で一般的に知られている nginx 向けの PATH_INFO の設定だと、location が
/.+\.php.+$
にマッチするのが前提だったりしなくもないので、それだと、DotCloud 的にはよろしくない。というのは、DotCloud の PHP 向けの nginx の設定が
location ~ /.+\.php$ { if ( -f /home/dotcloud/current/maintenance) { return 503; } try_files $uri /static/404.html; fastcgi_pass unix:/var/dotcloud/php5-fpm.sock; include fastcgi_params; include /home/dotcloud/current/*fastcgi.conf; }
となっているので、index.php/hoge とかにマッチしてくれない。
ならば /.+\.php.+$ にマッチする設定を approot/nginx.conf に書いておけば良いのかもしれないけど、fastcgi_pass のような DotCloud 環境依存な設定がそっちに記述されるのもどうかなと思うので、ここはゴリ押しで解決させておく。
index.php の先頭でこんなかんじで PATH_INFO のセットをしておいた
<?php if (!isset($_SERVER['PATH_INFO'])) { $request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; if (!empty($request_uri)) { $parsed_uri = parse_url($request_uri); $request_uri = isset($parsed_uri['path']) ? $parsed_uri['path'] : ''; } $_SERVER['PATH_INFO'] = $request_uri; }
rewrite とか
このあたりは DotCloud の Tutorial にあるように、try_files で設定しておくのがよさそう。$args も忘れずに。
try_files $uri $uri/ /index.php?$args;
よくある nginx.conf の設定だとここで
/index.php$requrest_uri
などをしておくことで PATH_INFO は設定するんだけど、そもそもこれは前述のとおり location でマッチできなくなるのでだめだった、というわけです。
まとめと雑感
- DotCloud いいかんじ
- サーバ建てるのとかデプロイとか超楽
- PaaS的なものが増えてきてほんとアプリケーションエンジニアがインフラ触る機会って今後減ってくるんだろうなーと思った
- Apache で簡単に動く PHP も好きだけど nginx な環境も最近は割と簡単に揃うし FPM とかも徐々に使われるようになるのかなーと思いつつ、色々な環境で動かせるようにしておくのは、たしかによさそう *2
- まあいずれにしても Apache べったり、じゃなくてもいい時代かもね
- DotCloud はその他ミドルウェアも充実してるからいろいろ遊びたいなー
- あ、ってことで Pastit っていう、設置型ペーストアプリを公開しました。これはもとも Internal な環境で (社内とか) snippet の共有が簡単にできるといいなーと思って作ったので、使いたい方は設置してみるといいかもしれません、結構便利ですよ。まだ embed できないけど。
Tiarra に設定を再読込させるための方法
PEAR で Unable to find the wrapper "channel" - did you forget to enable it when you configured PHP?
なんか出るよね最近。環境はDebian SqueezeのPHP 5.3.x。いや Lenny + dotdeb でも出る。(てか後述のとおり xdebug の設定だから環境依存じゃないかも。ちなみに PEAR は version 1.9.1)
検証してないけど channel:// を register してないのに使ってる気がする。
$ sudo pear upgrade-all PHP Warning: file_exists(): Unable to find the wrapper "channel" - did you forget to enable it when you configured PHP? in /usr/shar e/php/PEAR/Downloader/Package.php on line 1517 PHP Stack trace: PHP 1. {main}() /usr/share/php/pearcmd.php:0 PHP 2. PEAR_Command_Common->run($command = 'upgrade-all', $options = array (), $params = array ()) /usr/share/php/pearcmd.php:305 PHP 3. PEAR_Command_Install->doUpgradeAll($command = 'upgrade-all', $options = array (), $params = array ()) /usr/share/php/PEAR/Command/Common.php:271 PHP 4. PEAR_Command_Install->doInstall($command = 'upgrade-all', $options = array (), $params = array (0 => 'channel://components.ez.no/base', 1 => 'channel://components.ez.no/consoletools', 2 => 'channel://openpear.org/phpman', 3 => 'channel://pear.ethna.jp/smarty', 4 => 'channel://pear.ethna.jp/simpletest', 5 => 'channel://pear.ethna.jp/ethna', 6 => 'channel://pear.php.net/structures_graph', 7 => 'channel://pear.php.net/console_getopt', 8 => 'channel://pear.php.net/archive_tar', 9 => 'channel://pear.php.net/pear', 10 => 'channel://pear.php.net/xml_util', 11 => 'channel://pear.php.net/db', 12 => 'channel://pear.phpunit.de/dbunit', 13 => 'channel://pear.phpunit.de/file_iterator', 14 => 'channel://pear.phpunit.de/php_codecoverage', 15 => 'channel://pear.phpunit.de/phpunit', 16 => 'channel://pear.phpunit.de/phpunit_selenium', 17 => 'channel://pear.phpunit.de/php_timer', 18 => 'channel://pear.phpunit.de/text_template', 19 => 'channel://pear.phpunit.de/php_tokenstream', 20 => 'channel://pear.phpunit.de/phpunit_mockobject', 21 => 'channel://pear.symfony-project.com/yaml', 22 => 'channel://pear.twig-project.org/twig', 23 => 'channel://pecl.php.net/memcached', 24 => 'channel://pecl.php.net/xdebug')) /usr/share/php/PEAR/Command/Install.php:900 PHP 5. PEAR_Downloader->download($params = array (0 => 'channel://pear.php.net/structures_graph', 1 => 'channel://pear.php.net/cons ole_getopt', 2 => 'channel://pear.phpunit.de/php_codecoverage', 3 => 'channel://pear.phpunit.de/phpunit', 4 => 'channel://pear.phpunit.de/phpunit_selenium', 5 => 'channel://pear.phpunit.de/phpunit_mockobject', 6 => 'channel://pear.twig-project.org/twig')) /usr/share/php/PEAR/Command/Install.php:661 PHP 6. PEAR_Downloader_Package->initialize($param = 'channel://pear.twig-project.org/twig') /usr/share/php/PEAR/Downloader.php:278 PHP 7. PEAR_Downloader_Package->_fromFile($param = 'channel://pear.twig-project.org/twig') /usr/share/php/PEAR/Downloader/Package.php:160 PHP 8. file_exists('channel://pear.twig-project.org/twig') /usr/share/php/PEAR/Downloader/Package.php:1517 .. 延々と upgrade-all ok: channel://pear.php.net/Structures_Graph-1.0.4 upgrade-all ok: channel://pear.php.net/Console_Getopt-1.3.0 upgrade-all ok: channel://pear.phpunit.de/PHP_CodeCoverage-1.0.3 upgrade-all ok: channel://pear.phpunit.de/PHPUnit_Selenium-1.0.2 upgrade-all ok: channel://pear.phpunit.de/PHPUnit_MockObject-1.0.4 upgrade-all ok: channel://pear.twig-project.org/Twig-1.0.0RC1 upgrade-all ok: channel://pear.phpunit.de/PHPUnit-3.5.8 Warning: unlink(/tmp/glibctestQDzKXJ): No such file or directory in System.php on line 206 PHP Warning: unlink(/tmp/glibctestQDzKXJ): No such file or directory in /usr/share/php/System.php on line 206 PHP Stack trace: PHP 1. _PEAR_call_destructors() /usr/share/php/PEAR.php:0 PHP 2. call_user_func_array(array (0 => 'System', 1 => '_removeTmpFiles'), array ()) /usr/share/php/PEAR.php:774 PHP 3. System::_removeTmpFiles() /usr/share/php/PEAR.php:0 PHP 4. System::rm($args = array (0 => '-r', 1 => '/tmp/glibctestQDzKXJ')) /usr/share/php/System.php:440 PHP 5. unlink('/tmp/glibctestQDzKXJ') /usr/share/php/System.php:206
ああ、
1523 $this->_explicitGroup = true; 1524 } 1525 } 1526 1527 if (@is_file($param)) { 1528 $this->_type = 'local'; 1529 $options = $this->_downloader->getOptions(); 1530 if (isset($options['downloadonly'])) { 1531 $pkg = &$this->getPackagefileObject($this->_config, 1532 $this->_downloader->_debug);
@ 使ってるけど、僕の環境は xdebug.scream が On になってるから出るのね。PEARってほんとつくづく気持ち悪いよね。結構大きくなっててもう変えるのも直すのもだるいって話なんでしょうか(どこかで聞いたような話)。PEAR2に期待ってことですかね。。
エラーは出るけど @ つけて見えなくしてるから別にいいよねってかんじなんでしょうか。そんなやつは一度アレ *1を読みなおしてくると良いと思います。
追うの面倒だし、一応インストールはできてるから無視してる、が、気持ち悪い。
(とつぶやくだけのエントリーです。解決を期待した方すみません)
*1:え、この記事もう一昨年記事!?時間進みすぎじゃないすか?
Git で過去にさかのぼってタグ付けする (git tag)
もうだいぶ歴史を進めて開発進めてたんだけど、そういやあのプロトタイプが動いたときタグうっときゃよかったなーなどと思ったんだけど、意外と情報がなかったからメモ。
git-flow 使って、develop で開発進めてたりして、リモート/ローカルで push/pull も頻繁にしてるリポジトリ。現存するのは、develop, master のみ、だいぶ昔に feature/hoge からマージした段階に戻って master にマージしてタグ付けしたい、みたいな要望(割とあるよね?あるよね?
$ git log --all --graph
とか見ながら、コミットオブジェクトのハッシュ確認。例えば、「38fef39」が対象のコミットだとする。
そのハッシュをチェックアウト。
$ git checkout 38fef39 Note: checking out '38fef39'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at 38fef39... hogehoge
この時点では、どのブランチにも属していない状態になる。なので、一旦ブランチ切ってそこに入る。releaseブランチを切ってしまおう。
$ git branch -a * (no branch) develop master remotes/origin/develop remotes/origin/master $ git checkout -b release/0.0.1
masterをチェックアウトして、merge。no fast forward で。
$ git checkout master $ git merge --no-ff release/0.0.1
で、タグを打つ。
$ git tag -a 0.0.1
あとはブランチ削除
$ git branch -d release/0.0.1
完了!
2011 年もよろしくお願いします
結局例年通り、2010年まとめエントリは間に合いませんでしたが(w)、一応、まとめつつ、今年の目標など。
2010年のまとめ
もう面倒だから箇条書きでまとめますか。思いでエントリー。
- 1月
- 修論がんばってた
- 2月
- 修論終了、卒業決定
- 3月
- 大学院卒業。6年間の学生生活さようなら。
- 初アメリカ上陸。ベガスに卒業旅行。楽しかった。
- その他旅行色々した。遊び三昧の月だった。
- 4月
- 就職
- 色々生活が変わった。が、基本的にやってることは変わらなかったかな。
- とはいえ、色々新しいことと出会って、本当に楽しい出足。
- 5月
- 執筆必死。
- 6月
- 執筆必死。
- 7月
- 執筆必死。
- 8月
- 結婚した。
- そして引越しした。
- 祝われた。みんな本当にありがとう!!
- 9月
- PHPカンファレンス開催。主催側2年目。今年も広報がんばった。あとEthnaネタ発表した。
- MessagePack Hackathon に参加。その後うまいこと動けず、結果は出せなかったけど。久々にCとか触った。
- 10月
- reroomリリース(wozozoが)
- WEB+DB の特集執筆。人生初の雑誌記事書いた。
- 11月
- パーフェクトPHP発売&増刷。人生初の著書が発売された。本当に嬉しかった。そして評判も結構よくて更にうれしかった。
- 人付き合いに苦しんだw
- 12月
12月は盛りだくさんだったなあ。疲れた。4月〜7月くらいなんにも覚えてないなーとおもったら、振り返ったら執筆ばっかりやってたんですね。佳境でした。
まぁ、努力、実ってくれたからよかったかなw
うちの社長が言ってた言葉の中に刺さったものがあって、「毎年年末に、1年前を振り返ってみて、1年前には想像のできなかった自分になっていないとね」って話なんですが、これは良い言葉ですね。
で、今年どうなってたかというと、まあ、色々ありましたが、色々、今年は結構想像を絶する話が色々とあり、想像を超えることができたような気がします。
2011年
色々細かいところまで話すとキリがないけど、いくつか。
- 仕事:なにか1つ達成する
- nequal:大暴れする
今年もよろしくお願いします。
名前空間とautoload、標準的なClassLoaderの実装 (#phpadvent2010)
ってことで、アドベントカレンダーが回ってきたので書きます。なに書こうか迷いましたが、とりあえず、最近自分でも真面目に使い始めたPHP 5.3向けのClassLoaderと名前空間についての話です。
世の中的にずいぶん「これからはPHP 5.3だよね」的な流れがきているので、名前空間の区切りと、ディレクトリ構成、ファイル名、クラス名など、これから書くならどうするんだろ?ってところについておさらいしておきます。
PHP Standards Working Group
第1回のモダンPHP勉強会で、id:Fivestarが発表したように、Symfonyなどの開発者が集まって、このような内容をPHP界隈でちゃんと取り決めて標準っぽくしようよって話をしている、PHP Standards Working Groupというグループがあります。(最近あんま動きがないな)
このグループで議論がまとまっているものに、PSR-0 Final Proposal があり、この中で、名前空間の使い方・クラス名・ディレクトリの区切りはこうしよう、という意見がまとまってます。*1
例をあげると、以下のような感じ。
- \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php
- \Symfony\Core\Request => /path/to/project/lib/vendor/Symfony/Core/Request.php
- \Zend\Acl => /path/to/project/lib/vendor/Zend/Acl.php
- \Zend\Mail\Message => /path/to/project/lib/vendor/Zend/Mail/Message.php
ちなみにこのページはid:hnwさんが翻訳されています。
SplClassLoader を使ってみよう!
で、本題。標準的な名前空間とクラス名などの命名規則が決まれば、標準的なAutoloadクラスが作れるよねってことで作られたのが、SplClassLoaderです。SPLって名前が付いてるけど、別に組み込みでもないし、PHP的に標準になっているわけでもないので、「提案」レベルのものですが、SymfonyもこれをベースにClassLoaderをもっているし、まあ実質標準的なものであると考えてもらって問題ないです。
ってことで、これを使ってみましょう。
標準的なディレクトリ構成とクラスのファイルを用意
今回は、以下のような感じで作ってみました。
% tree . |-- Hoge | |-- Hogege.php | `-- Hogera | `-- Aho.php |-- SplClassLoader.php |-- entry_point.php `-- libs `-- vendors `-- Fuga `-- Foo.php
entry_point.php が実際にライブラリを使う側のファイル、Hoge と Fuga が、読み込まれる側のライブラリファイルだと想定し、Fuga はどこか変なとこにディレクトリがあるものだとします。まあ、よくある構成だはと思います。Aho.php Hogera.php Foo.php には実際にクラスが定義されていて、とりあえずコンストラクタが呼ばれると自分自身の名前空間とクラス名を出力するようにしてあります。
例えば次のような感じ:
<?php namespace Hoge\Hogera; class Aho { public function __construct() { echo __CLASS__, PHP_EOL; } }
実際に使ってみる
entry_point.php では、次のよう register() メソッドを呼び出し、名前空間とディレクトリのルートを指定したものを登録します。
<?php require 'SplClassLoader.php'; $class_loader_hoge = new SplClassLoader('Hoge', __DIR__); $class_loader_hoge->register(); $class_loader_fuga = new SplClassLoader('Fuga', __DIR__ . '/libs/vendors'); $class_loader_fuga->register(); $a = new Hoge\Hogege(); $b = new Hoge\Hogera\Aho(); $c = new Fuga\Foo();
この出力は、
Hoge\Hogege Hoge\Hogera\Aho Fuga\Foo
となります。
正しくHogeやFugaの名前空間のクラスが読み込まれましたね。
ClassLoaderの動きを追ってみる
ClassLoader の実装は簡単で、一言で説明すると、
これだけです。
では、
$class_loader_hoge = new SplClassLoader('Hoge', __DIR__); $class_loader_hoge->register();
この設定でAutoloadの設定をし、
$b = new Hoge\Hogera\Aho();
こう使ったときに、どう読み込まれるかというと、
<?php // 以下は、SplClassLoaderのロード部分の実装。 public function loadClass($className) { if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) { $fileName = ''; $namespace = ''; if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) { // 名前空間区切りが見つかれば、それを最後の名前空間区切り以下をクラス名として、 // クラス名と名前空間に分解する $namespace = substr($className, 0, $lastNsPos); // => "Hoge\Hogera" $className = substr($className, $lastNsPos + 1); // => "Aho" $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; // 名前空間の区切り文字 "\" を "/" に変換して、パス名にする // => "Hoge/Hogera/" } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension; // クラス名のアンダースコア "_" を "/" に変換して、拡張子をつける // そしてそれを、パス名に結合し、これをファイル名とする // => "Hoge/Hogera/Aho.php" require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName; // 最後に、設定してあるインクルードパスにファイル名を結合してrequireする // => "/home/sotarok/tmp/splclassloader/Hoge/Hogera/Aho.php" } }
だいたいこんなかんじで、SplClassLoaderのコンストラクタに指定したインクルードパスと、それ以下のパスが名前空間を含んだクラス名とマッピングされ、クラスが読み込まれます。実に単純ですね。
まんまでも使えるけど・・・
実際には、もうちょっとルーズに使いたかったので、registerNamespace()とかのstaticメソッドを定義して使ってます。*2
こうすると、
<?php ClassLoader::registerNamespace('Hoge', '/path/to/Hoge'); ClassLoader::registerNamespace('Fuga', '/path/to/Fuga');
なんてかんじでルーズに使えて素敵です。
というわけで
いよいよ、と思って名前空間を使いはじめると、まだまだノウハウが共有されていなくて(それでも出てきたほうですが)悩むことも多いと思いますが、参考になれば幸いです。
アドベントカレンダーのバトンは slumbers99 さんにお渡しします!
モダンPHP勉強会 #2 やります!
今回のテーマは、モダンなテンプレートエンジン Twig です!
パーフェクトPHPの発売&増刷記念トークとサイン会、プレゼントもあるよ!(多分)
みんな参加してね!
- 作者: 小川雄大,柄沢聡太郎,橋口誠
- 出版社/メーカー: 技術評論社
- 発売日: 2010/11/12
- メディア: 大型本
- 購入: 32人 クリック: 1,065回
- この商品を含むブログ (59件) を見る