PHPでテンプレートを作成時にディレクトリが変わる際の対応を考える

はじめに

前回投稿「【初心者向け】PHPで共通パーツ(テンプレート)を作る方法(注意事項あり)」の最後に、「読み込ませる側のファイルのディレクトリが変わると、共通パーツ側のパス(リンク等)が正しくなくなる」と書きました。

PHPでテンプレートを作る場合、外部のPHPファイルを読み込むのでパスを含め外部ファイルそのままが読み込まれます。

そのため、読み込む先のディレクトリが変わると、相対パスだとそのディレクトリが合わなくなります。

目次

PHPをそのまま読み込むとどうなるか

文章だけで説明するのが難しいのでまずは下をご覧ください。このようなディレクトリ構成のサイトを作るとします。

  • index.php
  • page
    • page_a.php
    • page_b.php
  • common
    • headerphp
    • footer.php
  • style.css
  • images

ヘッダー部分の共通パーツ「header.php」として、次のように記述します。

header.php

<header>
	<a href="index.php">リンクテキスト</a>
	<img src="images/***.jpg" alt="画像">
</header>

これを「index.php」に読み込ませるには次のようにソースを記述します。

index.php

<html>
	<head>
		<!-- 省略 -->
	</head>
	<body>
		<?php include 'common/header.php' ?>
		<main>
			<p>index.php単独の内容を記述</p>
		</main>
		<footer>
			<!-- 省略 -->
		</footer>
	</body>
</html>

「heder.php」のソースを「index.php」が読み込むので、再現すると以下のようになります。

index.php(再現)

<html>
	<head>
		<!-- 省略 -->
	</head>
	<body>
		<header> <!-- ここに header.php を読み込んでいます -->
			<a href="index.php">リンクテキスト</a>
			<img src="images/***.jpg" alt="画像">
		</header>
		<main>
			<p>index.php単独の内容を記述</p>
		</main>
		<footer>
			<!-- 省略 -->
		</footer>
	</body>
</html>

ではこれと全く同じ事を「page」ディレクトリ内の「page_a.php」に行うとどうなるかとうと、以下のようになります。

page > page.php(再現)

<html>
	<head>
		<!-- 省略 -->
	</head>
	<body>
		<header>
			<a href="index.php">リンクテキスト</a ><!-- ここのパスが合わなくなる -->
			<img src="images/***.jpg" alt="画像"> ><!-- ここのパスも合わなくなる -->
		</header>
		<main>
			<p>page_a.php単独の内容を記述</p>
		</main>
		<footer>
			<!-- 省略 -->
		</footer>
	</body>
</html>

「page_a.php」はルートディレクリから1つ下の階層にあるため、正しいパスは../index.php../images/***.jpgとする必要がありますが、「header.php」の記述そのままを読み込むので、リンクや画像のパスが合わなくなります。

格納するディレクトリをルートディレクトリに統一すれば問題は発生しませんが、中規模以上のサイトになるとディレクトリ構造を変える必要もあります。

この問題を何とかしたい、というのが今回の主旨です。

ディレクトリが変わる時の対策

対策の1つとして「相対パスではなく絶対パスで書く」という物があるのですが、この場合だとローカルでテストする時とサーバーアップ時でパスが変わり、いちいち書き直すのも面倒です。

そこで私なりに「ディレクトリを~するパスを変数として設定し、パスに読み込ませる」という方法を考えました。

私はPHPはそこまで詳しくないので、ひょっとしたらもっと良い方法があるかもしれません。調べた範囲で良い方法が見つからなかったのでこのようにしています。

先ほどの「index.php」「page_a.php」「header.php」を次のように修正します。

まず「index.php」と「page_a.php」に、ソース上部に変数「$root」を設定しました。それぞれのファイルが格納されたディレクトリからルートディレクトリまでの階層に合わせて値を設定します(「index.php」はルートディレクトリなので./。「page_a.php」なら../としています)。

「index.php」のようにルートディレクトリと同じ階層の値はブランクでも良いかもしれませんが、個人的にブランクだとしっくりこないので./と記述しています。

index.php

<?php $root = './' ?> <!-- ここを追記 -->
<html>
	<head>
		<!-- 省略 -->
	</head>
	<body>
		<?php include $root.'common/header.php' ?> <!-- ここを修正 -->
		<main>
			<p>index.php単独の内容を記述</p>
		</main>
		<footer>
			<!-- 省略 -->
		</footer>
	</body>
</html>

page > page_a.php

<?php $root = '../' ?> <!-- ここを追記 -->
<html>
	<head>
		<!-- 省略 -->
	</head>
	<body>
		<?php include $root.'common/header.php' ?> <!-- ここを修正 -->
		<main>
			<p>page_a.php単独の内容を記述</p>
		</main>
		<footer>
			<!-- 省略 -->
		</footer>
	</body>
</html>

次に読み込む先のファイル「header.php」を修正します。

「header.php」のパス部分の先頭に<?php echo $root ?>を追記します。

header.php

<header>
	<a href="<?php echo $root ?>index.php">リンクテキスト</a>; <!-- ここを修正 -->
	<img src="<?php echo $root ?>images/***.jpg" alt="画像">; <!-- ここを修正 -->
</header>

<?php echo $root ?>を記述する事で、「index.php」「page_a.php」それぞれに設定した値を代入させ、ルートディレクトリのパスに合わせる、という考え方です。

これで、PHPを設置するディレクトリに対応した$rootの値を設定する事で正しいパスを読み込ませる事ができます。

(あまり無いかもしれませんが)、既存のPHPファイルのディレクトリが変わった場合でも$rootの値を修正すればパスも修正できます。

ですので、私の場合「index.php」等に画像やリンクのパスを記述する場合にも、その先頭に<?php echo $root ?>を記述しています。

おまけ(個人的に気になっていること)

現時点で私はこのような方法を使っていますが、気になっている事が何点かあります。

今のところ何の問題も出ていないのですが、今後出てこないとも限りませんので念のため記しておきます。

  • 実はもっと単純で正しい方法があるかもしれない
  • $rootという変数名は単純すぎて外部ファイルの変数とバッティングする可能性があるので、もう少し複雑な方が良いかもしれない