PHPで現在のディレクトリ、上のディレクトリへと対象のファイルを探し出すコード
PHPでHTMLサイトのベーステンプレート化をしようと思い、設定ファイルをどの位置にあるファイルからでもパスの指定を相対的にしなくても出来るようにしようと思い今回、コードを作ってみました。
まず、目的ですが。どんな階層にあっても設定ファイルを相対パスや絶対パスで指定しなくても自動的に探しだして、読み込めるようにするというものです。
head.php footer.php side.php等を functions.php と同じ階層に設置し。functions.phpを一度呼び出せばそれらのファイルのパスを気にせずに呼び出せるようにするというものです。
functions.php と head.php とは同じ階層に必ずあるという条件なので function.php からはファイル名だけの指定でinclude出来ます。テンプレートファイルでinclude_onceでfunctions.phpを読みこめば あとは関数でテンプレート内でhead.php等を呼び出せます。パスを気にするのは、functions.phpだけでいいということになります。
サイトの階層がひとつのフラットな構成なら、テンプレートでfunctions.phpを呼び出すのは、ファイル名だけで出来ますが、子ディレクトリにある場合は相対パスか絶対パスでの指定が必要になります。相対パス、絶対パスともに子ディレクトリの階層によって個別に指定したものをテンプレートとしなければいけないので、ファイルで相対パス、絶対パスを指定していると。階層が変わるごとにその部分を変えてやらないといけないのでテンプレートが、かさばるし。テンプレートの使い間違いによるパスの間違いになりかねない。
そこで考えたのが、同じ階層にfunctions.phpがあるか?同じ階層になければ上の階層にあるか?その階層にもなければさらに上の階層にあるか?を繰り返していき、ファイルがあったところでその絶対パスを自動的に指定して、functions.phpを読み込めるようにするという方法です。
PHPで現在のディレクトリに特定のファイルがあるか、なければ上のディレクトリへと順番に探していくコード
$path = dirname(__FILE__); $file_aru = ""; $count = 0; while ( $count <= 10 ) { $count++; // カウント if ($dir = opendir($path)) { while (($file = readdir($dir)) !== false) { if ($file != "." && $file != "..") { if ( $file === 'functions.php' ) { //ファイルが見つかった時の処理。 $file_aru = "yes"; $path = str_replace("\\","/",$path); $path = $path."/functions.php"; } } } closedir($dir); } if( $file_aru === "yes") { break; } //ファイルが見つかったら ブレイクでwhile終了 $path = dirname($path); //ファイルが見つからなかったら、パスを一つ上がる } if ($file_aru === "yes") { include_once "$path";}
まずは、現在の階層を $path = dirname(__FILE__);
で取得し while (($file = readdir($dir)) !== false)
でその階層のファイルを全て取得します。その時に、特定のファイル(functions.php)が有った時にのみ実行する内容を作っておきます。無かった場合は $path = dirname($path);
で一つ上のディレクトリのパスを取得します。そして、繰り返していきます。ファイルが見つかった場合にそのパスに探していたファイル名を足して 絶対パスにします
あとはその絶対パスを元に、探しているファイルをincludeさせるだけで完了です。
階層を上がるところの処理は、初期値で10階層上までいってなければ終了するようにしてあります。最大数を指定しておかないと、処理が永遠に繰り返されてサーバーに負荷がかかりますので。とりあえず10階層にしてあります
ここのところは改善点で、ファイルの有る場所から取得した絶対パスから何階層目にあるのかを調べてそれを上下値に自動的に設定するようにする方がベストですね。
これで、同じフォーマットのテンプレートでどの位置にこのテンプレートを設定しても、functions.phpが呼び出せてパスを気にせずに使えるように出来ました。
COMMENT