2013年12月16日月曜日

RIsolutoのコードを読む その1 | Risoluto@アドベント・ぼっち・カレンダー:11日目

ABC(*1)の11日目。共通テーマは私が開発している「Risouto」についてです。



全ての源はindex.php


さて、今回からは「Risolutoのコードを読む」というテーマで書いていきますよ。これを読めばRisolutoを使ったユーザアプリケーションがどのように呼び出されるのかが理解でき、Risolutoのカスタマイズもやりやすくなるはずです。

ということで、初日の今日は、Risolutoのブートストラップといえばいいのかなんなのか、ともかく一番最初にコールされる「public_html/index.php」のコードを見ていくことにします。

ちなみにRisolutoのコンセプトとして、「外部公開を意図していないコードは極力ドキュメントルートに置かない」というスタンスがあったりなかったりなので、Risolutoの標準配布物(*2)に含まれるPHPプログラムとしてはこの「index.php」が唯一無二の存在なのです。……現時点ではね。

で、そのコードの中から、重要そうな部分をピックアップしていくわけですが、まずはこの部分から。

//------------------------------------------------------//
// 動作環境チェック
//------------------------------------------------------//
// PHPバージョンが指定された以前のものであれば強制終了
if (version_compare(PHP_VERSION, '5.5.0', '<')) {
    exit('Risoluto requires PHP 5.5.0 or later...');
}

// // OPTIONAL: URLの正規化
// if (isset($_SERVER['SERVER_NAME']) and !preg_match('/^www.*/i', $_SERVER['SERVER_NAME'])) {
//     header('Location: ' . ((isset($_SERVER['HTTPS']) and !empty($_SERVER['HTTPS'])) ? 'https' : 'http')
//                         . '://www.' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'], true, 301);
//     exit;
// }
こんな感じで先頭の方で、PHPのバージョンチェックをしてます。ご覧の通りPHP5.5系じゃなければこの時点で実行をストップ。それがRisolutoなのです。 で、その下には「OPTIONAL」なコードがコメントの状態で置いてあります。これ、何をするコードかと言いますと、例えば「example.com」でアクセスされたときに「www.example.com」にリダイレクトするためのコード。要は、「www」無しのURLでアクセスされたときに「www」有りのURLにリダイレクトさせるためのコードですね。 まあ、.htaccessとかでもできるんですが、PHPでやりたい人向けに事前に用意しています。ほとんどの環境では、この部分の先頭にある「// 」を削除すれば、ご期待通りの動作をすることでしょう。 ね?親切でしょ?(*3)
//------------------------------------------------------//
// 定数定義
//------------------------------------------------------//
define('RISOLUTODIR', dirname(dirname(__FILE__)));

define('RISOLUTO_DOCROOT', dirname(__FILE__));
define('RISOLUTO_SYSROOT', RISOLUTODIR . '/risoluto/');

define('RISOLUTO_APPS', RISOLUTO_SYSROOT . 'apps/');
define('RISOLUTO_CLI', RISOLUTO_SYSROOT . 'cli/');
define('RISOLUTO_CONF', RISOLUTO_SYSROOT . 'conf/');
define('RISOLUTO_DATA', RISOLUTO_SYSROOT . 'data/');
define('RISOLUTO_LIB', RISOLUTO_SYSROOT . 'lib/');

define('RISOLUTO_CACHE', RISOLUTO_DATA . 'cache/');
define('RISOLUTO_LOGS', RISOLUTO_DATA . 'logs/');
define('RISOLUTO_SESS', RISOLUTO_DATA . 'sess/');
define('RISOLUTO_UPLOAD', RISOLUTO_DATA . 'upload/');

define('RISOLUTO_LIB_VENDOR', RISOLUTO_LIB . 'vendor/');
で、その下には定数定義がずらっと。 基本的には、この「public_html/index.php」が配置されたディレクトリ、すなわちドキュメントルートとその親ディレクトリを起点として、ドキュメントと同階層にある「risoluto」っていうディレクトリ、およびその中にあるサブディレクトリへのパスを定数として定義しています。 ディレクトリ配置をカスタマイズしたいときなんかは、ここを変更すると幸せになれます。Risolutoの標準配布物では、ここに定義されている定数を使うように書いているはずなので(*4)。
//------------------------------------------------------//
// インクルードパスの変更
//------------------------------------------------------//
set_include_path(RISOLUTO_LIB_VENDOR . PATH_SEPARATOR
    . RISOLUTO_APPS . PATH_SEPARATOR
    . get_include_path());
インクルードパスについても動的に変更していたりします。まあ、特に使う予定もないので、将来のリリースでは削除するかもしれないけれど、とりあえずRisoluto 1.x系の名残……という感じのコードです。 インクルードパスに「risoluto/lib/vendor/」と「risoluto/apps/」の二つのディレクトリを追加して、その後ろにphp.iniなんかで定義されているインクルードパスをくっつけてる……すなわち、先の2ディレクトリを既存のインクルードパスの先頭に付加しているってコードです。
//------------------------------------------------------//
// オートローダ読み込みと設定
//------------------------------------------------------//
$autoloader = RISOLUTO_LIB_VENDOR . 'autoload.php';

clearstatcache(true);
if (file_exists($autoloader) and is_file($autoloader) and is_readable($autoloader)) {
    // オートローダが存在すれば読み込む
    require_once($autoloader);
} else {
    // 存在しなければ強制終了
    $path_lib = RISOLUTO_LIB;
    $path_dat = RISOLUTO_DATA;
    die(<<<"EOD"
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset = 'UTF-8'>
        <meta name = 'robots' content = 'NOINDEX,NOFOLLOW'>
        <title>Risolutoが動くまでもう少し!</title>
    </head>
    <body>
        <p>この必須ファイルが存在しないかロードできません: $autoloader</p>
        <p>下記の手順でセットアップしてください。環境によってはいくつかのソフトウェアをインストールしたり、設定を変更する必要があるかもしれません。</p>
        <ol>
            <li>cd $path_lib</li>
            <li>curl -sS https://getcomposer.org/installer | php</li>
            <li>php composer.phar install</li>
            <li>sudo chown -R {Webサーバの実行ユーザ}:{Webサーバの実行グループ} $path_dat</li>
        </ol>
        <p>セットアップが終了したら、この画面を再読込してください。</p>
    </body>
</html>
EOD
    );
}
んで、ここが一番のキモ。Risolutoのセットアップ手順では、composerをインストーするよう言われるわけですが、その結果生成されたPSR-0準拠のオートローダが存在するのかをまずチェックします。存在すれば、そいつをrequire_once()で読み込むだけなんですが、存在しない場合は、Risolutoのセットアップがまだされていないか正常に行われていない可能性がきわめて高いので、どうすればセットアップができるのか……を画面(Webブラウザ)上に表示するようなコードになってます。 Webサーバの実行ユーザと実行グループ以外は各環境に合わせて動的に取得するようになっているので、基本コピペすればセットアップできます。4つめのコードだけは環境に合わせて自分で考えなければいけませんが、結局の所Webサーバから書き込めるようになっていればいい……って話なので、「chmod 777〜」とかで対処しても大丈夫だったりします。Risoluto的にはオススメしてないってだけで。
//------------------------------------------------------//
// Risolutoコアクラスインスタンスの生成と実行
//------------------------------------------------------//
$risoluto_instance = new \Risoluto\Core;
$risoluto_instance->Perform();
で、ここまででRisolutoを実行するためのお膳立てが揃った訳なので、いよいよRisolutoのコアクラスをコールするわけです。 ちなみにここではrequireやincludeを行っていないわけですが、先のcomposerをセットアップした際に生成されるオートローダによってそこら辺はうまいこと処理されるようになります。どのようなことやってるのかを知りたいという場合は、「risouto/lib/composer.json」を見てみると良いです(*5)。 と、いうわけで、今回はこの辺で。また明日。
*1:アドベント・ぼっち・カレンダーの意
*2:要はリリースしたブツ
*3:親切の押し売りともいう
*4:そうなっていないコードを見かけたらそれはバグです
*5:namespaceによって見に行くディレクトリを決め打ちしている……っていえばわかりやすいかしら

0 件のコメント:

コメントを投稿