ホームページといえば、ヘッダー・グローバルナビゲーション・コンテンツ・サイドメニュー・フッターで構成されるのが一般的です。このうち、コンテンツを除く部分は各ページで共通していることが多いと思います。
WordPress をはじめとする CMS であれば、管理画面からの設定と少しばかりのテンプレート編集によって共通化できるのですが、静的 HTML サイトの場合にはこれを手作業によるコピー&ペーストで更新する必要があります。ページ数が少ないうちはいいのですが、サイト規模が大きくなるととんでもない手間に。うっ、数年前に何十ページ分もサイドバーをコピペした苦しい記憶が・・・。
今回は、このようなコピペ地獄による悲しいトラウマをみなさんに負わさないために、共通化できる部分をパーツとして取り出し、あらゆるページから参照する方法について調べてみました。
PHPを使います
共通部分パーツ化の方法にはいくつかの方法があります。
- Dreamweaver を使う
- JavaScript を使う
- PHP を使う
私は PHP を使うことにしました。理由は次のとおり。
- 私が Dreamweaver を使ったことがないので、よく知らない
- ブラウザで JavaScript を無効にしているユーザーには共通部分が表示されない
共通部分のパーツ化
今回使用する HTML は次のとおりです。ファイル名は home.html、文字コードは UTF-8 の BOM 無しで保存しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <!doctype html> <html> <head> <meta charset="utf-8"> <title>共通部分のパーツ化</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div class="header"> <h1>ヘッダー部分</h1> </div> <div class="main"> <h2>コンテンツタイトル</h2> <p>テキスト・テキスト・テキスト・テキスト・テキスト</p> </div> <div class="sidebar"> <div> <H2>新着記事</H2> <ul> <li><a href="">新着タイトル1</a></li> <li><a href="">新着タイトル2</a></li> <li><a href="">新着タイトル3</a></li> </ul> </div> <div> <H2>プロフィール</H2> <img src="images/profile.png"> <p>どーも、ブログ管理人の Naokix です</p> <p>俺の敵は だいたい俺です</p> </div> </div> <div class="footer"> Copyright (C) 2016 Naokix.net All Rights Reserved. </div> </body> </html> |
説明のために簡略化しているので、スタイルシートによる装飾を施していないです。一般的なサイトではヘッダー部分にグローバルナビゲーションが設置されていると思いますが、そちらも省略しています。
先ほどの HTML からヘッダー、サイドバー、フッターをそれぞれコピーして PHP ファイルとして保存します。PHP を扱うので、文字コードは UTF-8 の BOM 無しにしてください。
header.php
1 2 3 | <div class="header"> <h1>ヘッダー部分</h1> </div> |
sidebar.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <div class="sidebar"> <div> <H2>新着記事</H2> <ul> <li><a href="">新着タイトル1</a></li> <li><a href="">新着タイトル2</a></li> <li><a href="">新着タイトル3</a></li> </ul> </div> <div> <H2>プロフィール</H2> <img src="images/profile.png"> <p>どーも、ブログ管理人の Naokix です</p> <p>俺の敵は だいたい俺です</p> </div> </div> |
footer.php
1 2 3 | <div class="footer"> Copyright (C) 2016 Naokix.net All Rights Reserved. </div> |
次に先ほどの HTML を次のように編集します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!doctype html> <html> <head> <meta charset="utf-8"> <title>共通部分のパーツ化</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <?php include(dirname(__FILE__).'/header.php'); ?> <div class="main"> <h2>コンテンツタイトル</h2> <p>テキスト・テキスト・テキスト・テキスト・テキスト</p> </div> <?php include(dirname(__FILE__).'/sidebar.php'); ?> <?php include(dirname(__FILE__).'/footer.php'); ?> </body> </html> |
相対パスで運用するつもりなため、各 PHP ファイルのパス指定に dirname(__FILE__) を使っています。ディレクトリの最後にスラッシュが付かないので、読み込むファイル名の頭に入れ忘れないようにしてください。
保存したファイルをひとつのフォルダにまとめ、XAMPP であれば htdocs 以下に移動します。
アクセスするには、ブラウザのアドレスバーに http://localhost/test/home.html のように入力すればよいです。
動作確認の前に
今回 XAMPP で動作確認を行いますが、このままではうまく動作しません。「.html ファイルでも PHP を動作させるよ」という設定をサーバーにしてやる必要があります。.htaccess ファイルに次の一行を記述し、home.html ファイルと同じフォルダに保存します。
1 | AddType application/x-httpd-php .php .html |
文字コードには特に指定がないようです。私は Shift-JIS で保存しました。
.htaccess ファイルですが、これは保存してあるフォルダとその下位のフォルダに対して設定を行うファイルです。今回は上の一行で設定を行って XAMPP で動作確認をしましたが、レンタルサーバーの構成によっては違う指定方法をしなければならないことがあります。
レンタルサーバーのマニュアルや Q&A などに指定方法が書いてあったりしますが、わからなければユーザーサポートに問い合わせて確認するようにしてください。
違う階層のフォルダからも共通化部分を呼び出す
サイトのページ数が増えてくると、フォルダを使ってファイルを整理することがあると思います。
当然、階層が異なるファイルであってもパーツ化された共通部分を呼び出したいのですが、今までの記述のままではうまくいきません。例えば、上のようなフォルダ階層で seihin.html を次のように記述したとします。呼び出すパーツが seihin.html のひとつ上の階層になっているので、include でのファイル指定に修正が必要なことに注意してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!doctype html> <html> <head> <meta charset="utf-8"> <title>共通部分のパーツ化</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <?php include(dirname(__FILE__).'/../header.php'); ?> <div class="main"> <h2>コンテンツタイトル</h2> <p>テキスト・テキスト・テキスト・テキスト・テキスト</p> </div> <?php include(dirname(__FILE__).'/../sidebar.php'); ?> <?php include(dirname(__FILE__).'/../footer.php'); ?> </body> </html> |
これを動作させると、サイドバーのプロフィール画像が読み込まれていないことがわかります。
これは product フォルダが相対パスの基点になっているので、サイドバーで呼び出している画像ファイルを参照できなくなってしまったためです。これを解決するには、それぞれのファイルを少しばかり修正する必要があります。
seihin.html
1 | <?php $path = "../"; include(dirname(__FILE__).'/../sidebar.php'); ?> |
sidebar.php
1 | <img src="<?php print $path; ?>images/profile.png"> |
これは共通化パーツを呼び出す側のファイルの現在の階層を変数に代入し、呼び出される PHP ファイル内でアドレスに追記しているものです。階層が深くなれば ../../、../../../・・・と増えていくことになります。
これにあわせて、一番上の階層に置いてある home.html の呼び出し部分も修正します。
home.html
1 | <?php $path = "./"; include(dirname(__FILE__).'/sidebar.php'); ?> |
これで画像ファイルを読み込んでいる PHP ファイルをどの階層から呼び出しても、ちゃんと画像が表示されるようになると思います。
includeか?それともrequire_onceか?
この話題をネットで調べると、PHP ファイルを読み込むのに include を使っている例がほとんどだと思います。include、include_once、require、require_once のうちどれを使えばいいのか混乱することもあるかと思いますが、こちらのリンクによれば include か require_once のどちらかを考えればよく、それ以外は考慮する必要がないと説いています。
include と require_once の使いわけ – 昨日知ったこと
台本の「セリフ」と「ト書き」を参考にどのように使い分ければよいのかを解説されていますが、HTML のみ書かれたファイルを読み込む場合には include、PHP を使ったファイルであれば require_once を使えばよいと私は解釈しました。
WordPress を使ったことのある人ならご存知だと思いますが、WordPress のテーマでパーツを共通化するには get_header、get_sidebar、get_footer といった関数を使います。実は、WordPress のコアファイルをたどっていくと、最終的には require_once を使って PHP ファイルを呼び出していることを確認することができます。wp-includes/template.php に locate_template、load_template という関数が定義されているので、処理を追ってみてください。
今回の場合、print 関数でパスを記述するだけの単純な処理なので、include でも動作してしまいます。ただ、今後サイトを作りこんでいくと複雑な PHP を記述する必要が出てくる可能性もあり、関数の再定義などで挙動がおかしくなることがあるかもしれません。
原因がよくわからないバグで後々悩まされないためにも、require_once で PHP ファイルを呼び出すようにしたほうがよいかと思います。
Comment