2013/03/21

[PHP]相対パスじゃないinclude_pathのファイルを指定してincludeしたい

私ごときがPHPの記事を書くなんておこがましいし、おおよそ間違ってるかもしれませんが、ちょっと思いつきで書いてみます。たぶんバッドノウハウです。

PHPのinclude_pathは実行しているファイルからの相対パスとライブラリ群の保管場所を指定していると思います。
で、相対パスとライブラリ群の保管場所に同じファイル名があるんだけどライブラリ群の方のファイルをrequire_onceしたい場合にどうすれば?
っていう話です。

まぁ同じパスに同じファイル名置かなきゃいいだけの話です。わかってます。





例えばこんな感じ。

php.ini
; Windows
include_path = ".;C:\php\pear"
; Linux
include_path = ".;/path/to/php/pear"
いやもうウチはpearとか使ってませんけどね。あくまで例です。


Googleで検索すると

「相対パスのファイルを指定したいなら」ってことで__DIR__を使う方法とかがヒットするんですが、その逆は見つからなかったのです。
そもそも上のようなiniの書き方なら先に相対パスが見つかるので別に「相対パスのファイル」を指定したくて困ることはありません。

困るのはこういう場合です。

include_path
├entry.php
└file.php ←読み込みたいファイル

__DIR__
├index.php ←最初に呼び出したファイル
└file.php ←相対になぜかある同じファイル名のファイル

こうなっていると、
require_once file.php;
って書くと当然同じディレクトリにあるfile.phpが読み込まれます。
require_once ./file.php;
でも同じ。(当たり前)

繰り返しですが同じディレクトリにあるファイルの名前を変えればいいだけなんですが、配置や命名規則のイレギュラーを作るのもむかつくのでできれば場所や名前を変えたくない場合もありますよね?ね?ね?


じゃぁどうすればいいのさっ。

そう、一時的にinclude_pathを書きかえればいいんです(キリッ

マニュアルを見ると include_path はPHP_INI_ALLで変更可能なので ini_set()できます。
ってことで関数を作ってみました。
/**
 * 相対パス以外のinclude_pathから読み込む
 *
 * @param string $filename  読み込むファイル名
 * @param string $structure 言語構造の指定(require_once/require/include_once/include)
 * @throws Exception
 * @return void
 */
function read_except_relative_path($filename, $structure = 'require_once')
{
    // iniのinclude_pathを変数に入れておく
    $ini_include_path = ini_get('include_path');
    // 相対パスを除いた文字列を生成する
    $temp_include_path = str_replace('.;', '', $ini_include_path);
    // ini_setで相対パスを除いたinclude_pathをセットする
    ini_set('include_path', $temp_include_path);
    // 指定した言語構造で読み込む
    switch ($structure) {
        case 'require_once':
            require_once $filename;
        break;
        case 'require':
            require $filename;
        break;
        case 'include_once':
            include_once $filename;
        break;
        case 'include':
            include $filename;
        break;
        // 言語構造がおかしい場合はやにわに例外を投げるので誰か受け取ってください 
        default:
            throw new Exception('Bad Control Structure "' . $structure . '".');
        break;
    }
    // iniのinclude_pathに戻しておく
    ini_set('include_path',$ini_include_path);
}

set_include_path()とかget_include_path()を使ったほうがモダンなのかもしれませんね。

0 件のコメント:

コメントを投稿