既存のPHPプロジェクトをZend Frameworkのプロジェクトに
やりたい事
タイトル通りだけど、既存のPHPプロジェクト(フレームワークとかは特に使っていない)をZend Frameworkのプロジェクトに移行する。
参考ページ
基本はこのページのとおり。
具体的な処理の流れは以下の通り。
- mod_rewrite で、ディレクトリに対するアクセスなどはZend Frameworkに飛ばす
- それ以外の、実際に存在する PHP ファイル、画像ファイルなどは今までどおり処理。
手順
Zend Frameworkのプロジェクト作成
適当なディレクトリでZFのプロジェクトを作成(projectxという名前)。
$ zf create project projectx
色々ファイルができるので、それを /var/www/html 配下に移動。
$ mv projectx/* /var/www/html
既存のファイル、ディレクトリと名前が被る場合は、既存のプロジェクトの方を適当に修正する。
mod_rewrite の設定
.htaccess とかに以下のように記載。参考にしたページの内容とは若干変えている。
RewriteCond %{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_FILENAME} \.php$ [OR] RewriteCond %{REQUEST_FILENAME} =/ RewriteRule ^(.*)$ /public/index.php/$1 [L,NS]
- リクエストが以下の「どれか」を満たす時、/public/index.php が呼ばれる。
- ファイルでない(ディレクトリと、それ以外に何かあったっけ?)
- ファイル名が .php で終わる
- /
- それ以外の画像ファイル・CSS・JavaScript とかは、この RewriteRule が適用されずにそのまま呼ばれる。
基本的な仕組みとしては、php ファイルに対するアクセスは全て public/index.php が処理をする
mod_rewrite に関しては、詳しくはApacheのドキュメントを参照。
public/index.php
ここでやりたい事は、以下の通り。
ファイルの中身は以下の通り。
<?php // Define path to application directorydefined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../library'), get_include_path(), ))); //ここがキモ $request = new Zend_Controller_Request_Http(); $docroot = $request->get('DOCUMENT_ROOT'); $uri = $request->getPathInfo(); // 1. これだとダメだった $path = $_SERVER['PATH_INFO']; $filePath = $docroot . $path; if (is_file($filePath)) { // 2. file_exists だとディレクトリでも true になる chdir(dirname($filePath)); // 3. これがないと require_once でエラーになるケースも ob_start(); include $filePath; $response = new Zend_Controller_Response_Http(); $response->setBody(ob_get_clean()); $response->sendResponse(); exit; } /** Zend_Application */ require_once 'Zend/Application.php'; // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap() ->run();
コードの中でコメントを書いている所が、参考にしたサイトと違う箇所。3箇所あるので順に説明。
1. アクセスされたURI→実際のファイル名への変換
元のコードだと、mod_rewrite で URLが書き換わっている場合にうまくいかなかった。
2. file_exists だとディレクトリでも true になる
file_exists だとディレクトリでもtrueが返るので、その後のinclude でエラーになる。is_file にすればOK。
3. chdir でディレクトリを変更
/var/www/html/page.php から /var/www/html/lib/someclass.inc.php を読み込んでいる場合を考える。
page.php の中身は以下のような感じ。
<?php // page.php require_once('lib/someclass.inc.php'); // エラー ?>
http://example.com/page.php にアクセスすると、エラーになる。理由は以下の通り。
- mod_rewrite により public/index.php が呼び出され
- そこから /var/www/html/page.php が includeされる
- この場合、カレントディレクトリは /var/www/html/public なので、page.php の require_once が失敗する
<?php // page.php require_once(__DIR__ . '/lib/someclass.inc.php'); // こうなってればOKだけど・・・ ?>
応用編
mod_rewrite を使っている場合もこれでOK
SEOの為に mod_rewrite を使ってURLを書き換えている場合でも、上の設定でOK。
参考ページではわざわざZFの custom route を作っていたけど、実際には必要ない。
phpMyAdmin 等、複雑なものの場合
さっきの設定で基本的には大体大丈夫なんだけど、複雑なシステムの場合はダメかもしれない。自分のところの例で言うと、phpMyAdmin が上手くいかなかったので、.htaccess に以下のルールを追加して例外扱いにしている。
RewriteCond %{REQUEST_URI} ^/phpMyAdmin/(.*)$ RewriteRule ^.*$ - [L]
まとめ
レガシーコードは一気に置き換えるのではなくて、徐々に置き換えていった方がいいと思う。
Zend Framework は今回初めて使ったんだけど、単なるライブラリとしても使えるので、
- まずはライブラリとして導入
- 徐々にフレームワークに移行
ってやるのもいいかな、と。