2013年12月18日水曜日

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

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



呼び出すクラスはなんだろな?


さて、本日もRisolutoのコアコードとも言うべき「risoluto/lib/vendor/Risoluto/Core.php」のコードを見ていくことにします。

前回はアプリケーションのクラスインスタンスを生成して、どのメソッドをどのようにコールするのか……という一連の流れについて見てみました。

今回はどのクラスをコールするのかをどう決定しているか……という点について見ていきましょう。それを担当しているのは「Core::FindClassClass()」というメソッドです。

    /**
     * FindCallClass()
     *
     * クラス内で発生したエラーに対するエラーメッセージを生成する
     *
     * @access    private
     *
     * @param     void なし
     *
     * @return    array   呼び出すクラスの情報等
     */
    private function FindCallClass()
    {
        // コンフィグファイルの読み込み
        $conf = new Conf;
        $conf->Parse(RISOLUTO_CONF . 'risoluto.ini');

        // デフォルトの情報をセット
        $load  = $conf->GetIni('SEQ', 'default');
        $param = '';

        // GETパラメタ中の情報(「seq」)が指定されていればそれを採用
        if (isset($_GET['seq']) and !empty($_GET['seq'])) {
            // 「.」が付いていたらそこで分割
            if (strpos('.', $_GET['seq']) === false) {
                $sep = explode('.', $_GET['seq']);

                // 分割後、1つめの要素は画面指定とみなし、2つめ以降の要素はパラメタと見なす
                $load = 'RisolutoApps\\' . $sep[0];

                unset($sep[0]);
                foreach ($sep as $dat) {
                    $param[] = $dat;
                }
                // 「.」が付いていなければそのまま採用する
            } else {
                $load  = 'RisolutoApps\\' . $_GET['seq'];
                $param = '';
            }

            // $load中の「_」を「\」に置換
            $load = str_replace('_', '\\', $load);

                    // 指定されたアプリケーションが存在していなければエラーとする
            $target = RISOLUTO_APPS . str_replace('\\', DIRECTORY_SEPARATOR, $load) . '.php';
            clearstatcache(true);
            if (!file_exists($target) or !is_file($target) or !is_readable($target)) {
                $load  = $conf->GetIni('SEQ', 'error');
                $param = '';
            }
        }

        // サービスストップファイルが存在するかロードアベレージが一定値以上ならサービスストップ
        $loadavg = sys_getloadavg();
        clearstatcache(true);
        if (file_exists(RISOLUTO_SYSROOT . 'ServiceStop') or $loadavg[0] > $conf->GetIni('LIMITS', 'max_loadavg')) {
            $load  = $conf->GetIni('SEQ', 'servicestop');
            $param = '';
        }

        // 決定した情報を返却する
        $retval = array('load' => $load
        , 'param'              => $param);

        return $retval;
    }

はじめにRisolutoが用意しているConfクラスのインスタンスを生成しています。ここで、Risolutoのコンフィグファイルである「risoluto/conf/risoluto.ini」をロードします。ちなみにこのファイル、Ini形式になってます。ちなみにこのConfクラス、「Conf::Parse)」メソッドで対象のIniファイルを読み込み&パースして、「Conf::GetIni()」メソッドでファイル中の書く定義を取得する……という作りになってます。はい。

「?seq=〜」が指定されていない場合は、risoluto.iniに定義されたデフォルトのアプリケーションがコールされ、指定されている場合はそのアプリケーションがコールされる。アプリケーションが存在しない場合など、エラーが発生した場合はエラーアプリケーションが、専用の指示ファイルが存在するかサーバのロードアベレージがrisoluto.iniに定義された値を超えた場合はサービスストップアプリケーションがコールされる。

まあ、それだけなんです。はい。

「?seq=〜」の指定については、過去のアドベント・ぼっち・カレンダーですでに解説している……ということにしておきたいと思うので省略します。はい。

エラー発生、その時は


さて、前回のPOSTで「Core::Perform()」メソッドで必須メソッドが無かったときは例外をThrowする……って話をしたと思うんだけども、そのときに「Core::CoreError()」メソッドってのをコールしているのにお気づきかと思います。

コイツは何者か……というと、このCoreクラスで発生したエラーメッセージを生成するのに加えて、ログにそのエラーを出力するというお仕事をしています。

    /**
     * CoreError($key = '')
     *
     * クラス内で発生したエラーに対するエラーメッセージを生成する
     *
     * @access    private
     *
     * @param     string $key なし
     *
     * @return    string    エラーメッセージ
     */
    private function CoreError($key = '')
    {
        // 引数の値に応じてエラーメッセージをセットする
        switch ($key) {
            // イニシャライズメソッド未定義エラーの場合
            case 'notfound_init':
                $msg = 'Required method is not exists - Init()';
                break;

            // コントローラメソッド未定義エラーの場合
            case 'notfound_play':
                $msg = 'Required method is not exists - Play*()';
                break;

            // エラーハンドリングメソッド未定義エラーの場合
            case 'notfound_error':
                $msg = 'Required method is not exists - Error()';
                break;

            // クリーニングメソッド未定義エラーの場合
            case 'notfound_clean':
                $msg = 'Required method is not exists - Clean()';
                break;

            // 未定義のエラーの場合
            default:
                $msg = 'Unknown Error occurred';
                break;
        }

        // ログ出力しエラーメッセージを返却
        $conf = new Conf;
        $conf->Parse(RISOLUTO_CONF . 'risoluto.ini');

        $log = new Log;
        $log->SetCurrentLogLevel($conf->GetIni('LOGGING', 'loglevel'));
        $log->Log('error', $msg);

        return $msg;
    }

まあ、メソッドコール時に指定されたパラメタに応じてエラーメッセージを決定し、ConfクラスインスタンスとLogクラスインスタンスを生成、ログに必要な情報をrisoluto.iniファイルから取得し、実際のログ出力を行う……というのが大まかな流れ。

ちなみにLogクラスには「ログレベル」の概念(*2)があるので、risoluto.iniでログレベルを指定することによって出力するログを制御する事ができます。「Log::SetCurrentLogLevel()」が現在のログレベル指定で、「Log::Log()」で実際のログ出力(*3)ですな。

戻り値としてメッセージを返却します。

まあ、そんなこんなでみんなが作ったアプリケーションがコールされるわけです。そんな感じです。って事でまた明日。


*1:アドベント・ぼっち・カレンダーの意
*2:まあよくあるアレね
*3:第一引数がそのログのログレベル、第2引数が出力するメッセージ

0 件のコメント:

コメントを投稿