dirname(__FILE__),__DIR__,$_SERVER[“DOCUMENT_ROOT”]が地味に分かりにくいので検証
今まで何となく検索で出てきた「dirname(__FILE__)」「__DIR__」を利用して、
「require」や「include」をしてきたphpファイルなのですが、
システム改変の規模が大きくなってきて限界に達したサイトが出てきたため、
改めてどうなのかをチェックしてみましたのでご紹介しておきます。
概要
検証したパターン
「require」や「include」を利用して別のphpファイルを読み込むパターンとして、
大まかに分けて以下の様なケースがあるのではないでしょうか。
P | 読み込み経路 | 備考 |
---|---|---|
① | functions.php | WordPress流 |
② | functions.php→/dir_a/require_test.php | WordPressで別ファイル読み込み |
③ | functions.php→/dir_a/require_test.php→/dir_b/require_test.php | WordPressで別ファイルが別ファイル読み込み |
④ | /dir_a/require_test.php | phpファイルを直接指定実行 |
⑤ | /dir_a/require_test.php→/dir_b/require_test.php | phpファイルを直接指定実行時に別ファイル読み込み |
こうしたパターンで共通で「require」や「include」のパス指定を、
ローカル環境(Windows)と環境依存なく読み込めるパス指定の方法を模索します。
検証結果
各パターンで検証した結果としてそれぞれ以下の様なパスを得ることができました。
以下の通りではありますが、
一般的に利用される「dirname(__FILE__)」「__DIR__」では、
Windows環境で受け取るパスが「\(バックスラッシュ)」になっているのが分かります。
これまでもずっとこのローカルと公開サーバーの差異を、
なんとなく条件分岐で回避してきたのですが、リリースの度に無駄にエラーに出会い、
いい加減、もう解決しようと腰をあげたという訳です。
$_SERVER[“DOCUMENT_ROOT”]
一番、安定してパスの取得ができるのがやはりこの記述方法です。
ローカル環境の公開フォルダまでのフルパスと、
サーバー環境の公開ディレクトリまでのフルパスが、
どのようなファイル読み込みパターンでも安定して取得ができ、かつ、
Windows環境でもフォルダの区切り「\」が「/」として取れ、環境依存が解消されています。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com |
/{server_file_path} /public_html/XXXXX.rensrv.com |
② | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com |
/{server_file_path} /public_html/XXXXX.rensrv.com |
③ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com |
/{server_file_path} /public_html/XXXXX.rensrv.com |
④ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com |
/{server_file_path} /public_html/XXXXX.rensrv.com |
⑤ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com |
/{server_file_path} /public_html/XXXXX.rensrv.com |
最初から、この方法にしておけばいいのに・・・と思いつつも、
Webで検索すると「dirname(__FILE__)
」「__DIR__
」に関する記述が多い事と、
むしろ「フルパスでファイル指定しよう!」という記述が多いので、
これまで「いや、フルパスの取得に困っているんだがなぁ・・・」と思ってきました。
これで良さそうです。
そもそも何故こんな検証をしたのかというと、
以下の大ハマりがあって、なぜかWindows(ローカル)だと、
「$_SERVER[“DOCUMENT_ROOT”]」の返すパスに、
「末尾にスラッシュが付いてくる」症状に悩んでいたからでした。
結果は、ものすごくクソみたいな凡ミスなだけでしたけども。。。
$_SERVER[“SCRIPT_FILENAME”]
ちなみに「$_SERVER["SCRIPT_FILENAME"]
」指定で行った場合には、
PHP実行起点となったファイルが取得できます。
WordPressであればすべてドキュメントルート(又は、WordPressインストールディレクトリ)にある
index.phpが処理の起点になっていますので、
functions.phpで記述した場合でも、統一したファイル名が取得できます。
ただ、WordPress外の独自ファイルを直接実行したような場合は、
そのファイルが起点になる事には注意が必要です。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com/index.php |
/{server_file_path} /public_html/XXXXX.rensrv.com/index.php |
② | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com/index.php |
/{server_file_path} /public_html/XXXXX.rensrv.com/index.php |
③ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com/index.php |
/{server_file_path} /public_html/XXXXX.rensrv.com/index.php |
④ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com/dir_a/require_test.php |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a/require_test.php |
⑤ | H:/subversion/{local_file_path_Slash} /XXXXX.rensrv.com/dir_a/require_test.php |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a/require_test.php |
__DIR__
さてよく見かける「__DIR__
」です。
便利な関数だとは思うのですが、如何せんWindows環境で開発をしている場合は、
パスが「\」で区切られて返されます。
続けて、読み込みたいファイルパスを記述するとすれば、
ローカルでは「\」、公開サーバーでは「/」と使い分ける必要があります。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\wdps\wp-content\themes\twentyseventeen |
/{server_file_path} /public_html/XXXXX.rensrv.com/wdps/wp-content/themes/twentyseventeen |
② | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_a |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a |
③ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_b |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_b |
④ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_a |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a |
⑤ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_b |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_b |
※「{…}」部は一部省略している事を示します。
dirname(__FILE__)
次もよく見かける「dirname(__FILE__)
」です。
こちらも便利な関数だとは思うのですが、
如何せんWindows環境で開発をしている場合はパスが「\」で区切られて返されます。
続けて、読み込みたいファイルパスを記述するとすれば、
ローカルでは「\」、公開サーバーでは「/」と使い分ける必要があるのは同じです。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\wdps\wp-content\themes\twentyseventeen |
/{server_file_path} /public_html/XXXXX.rensrv.com/wdps/wp-content/themes/twentyseventeen |
② | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_a |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a |
③ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_b |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_b |
④ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_a |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_a |
⑤ | H:\subversion\{local_file_path_BSlash} \XXXXX.rensrv.com\dir_b |
/{server_file_path} /public_html/XXXXX.rensrv.com/dir_b |
以下はオマケになります。
パスとは関係ないですが、ローカル、公開サーバの条件分岐には便利かと思います。
$_SERVER[“HTTP_HOST”]
ローカル環境か、公開サーバーかを判断するには、
単純にドメインで判別するのが一番簡単な方法でしょう。
「$_SERVER["HTTP_HOST"]
」を参照して条件分岐すれば、
「__DIR__
」「dirname(__FILE__)
」でも分岐はできそうです。(私の現在地がここでした)
P | ローカル環境 | サーバー環境 |
---|---|---|
① | XXXXX.domain.local | XXXXX.rensrv.com |
② | XXXXX.domain.local | XXXXX.rensrv.com |
③ | XXXXX.domain.local | XXXXX.rensrv.com |
④ | XXXXX.domain.local | XXXXX.rensrv.com |
⑤ | XXXXX.domain.local | XXXXX.rensrv.com |
$_SERVER[“SCRIPT_NAME”]
こちらはちなみに「$_SERVER["SCRIPT_FILENAME"]
」と似ていますが、
公開ディレクトリ(フォルダ)以下の相対パス向けの実行ファイル名までのパスが取得できます。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | /index.php | /index.php |
② | /index.php | /index.php |
③ | /index.php | /index.php |
④ | /dir_a/require_test.php | /dir_a/require_test.php |
⑤ | /dir_a/require_test.php | /dir_a/require_test.php |
$_SERVER[“SERVER_ADDR”]
ローカル環境か、公開サーバーかを判断するには、
単純にIPで判別することもできますが、IPは変わる可能性もありますし、
あまり使わないのではないでしょうか。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | 192.168.0.3 | 112.78.xxx.xxx |
② | 192.168.0.3 | 112.78.xxx.xxx |
③ | 192.168.0.3 | 112.78.xxx.xxx |
④ | 192.168.0.3 | 112.78.xxx.xxx |
⑤ | 192.168.0.3 | 112.78.xxx.xxx |
$_SERVER[“SERVER_NAME”]
「$_SERVER["HTTP_HOST"]
」同様に「$_SERVER["SERVER_NAME"]
」でも、
ドメイン名が取得できますが、
サーバーによっては「httpd.conf」に「ServerName xxx.yyy.com」など、
別のサーバー名が割り当てられていたり、
「httpd-vhosts.conf」の「ServerName xxx.yyy.com」などが返されてくるはずです。
ドメイン名と一致していない環境では注意が必要かもしれません。
P | ローカル環境 | サーバー環境 |
---|---|---|
① | XXXXX.domain.local | XXXXX.rensrv.com |
② | XXXXX.domain.local | XXXXX.rensrv.com |
③ | XXXXX.domain.local | XXXXX.rensrv.com |
④ | XXXXX.domain.local | XXXXX.rensrv.com |
⑤ | XXXXX.domain.local | XXXXX.rensrv.com |
シームレスに共通ソースでinclude,requireする方法を考える
単純に利用しているすべてのphpファイルで以下のように指定すれば、
ローカル、サーバー環境の差異無く、includeやrequireのパス指定はフルパスで行えるでしょう。
require ( $_SERVER['HTTP_HOST'] . '/dir_a/require_test.php' );
たぶん、結論はこれで終わりで、
ファイルの読み込みの際には「$_SERVER['HTTP_HOST']
」からパスを取ればいいという事になります。
最近はオートローダーなどの仕組みもあり、
あまり意識する事はないのかもしれませんが。
個人的には「$_FULLPATH」などの形でアクセスできる変数でも定義しておきたいところですが。
グローバルよりクラスのプロパティーの方がいいのかな・・・。
当サイト内のコンテンツおよび画像を含むすべてにおいて、管理人アルゴリズンが著作権を保持しております。
当サイトでご紹介しております写真等につきましては著作権の放棄はしませんが、
ライセンスフリーでご利用いただいて構いません。
コンテンツを有益であると感じていただけましたら非常に光栄です。
ありがとうございます。
サイト内コンテンツを引用される際には、出典元として当サイト(個別記事)へのリンクをお願いいたします。
申し訳ございませんが、無断転載、複製をお断りさせて頂いております。
公開日: