include と require_once の使いわけ

差し込みたければ include、利用したければ require_once

PHP には、外部のファイルを読み込む組込みの関数が複数個ある。使いわけがわからない、という声を聞くが、さほど難しくないよ、というのがここで私が主張したいこと。
結論から言えば、外部のファイルをそこに差し込みたい場合は include を使い、外部のファイルに定義されたものを使いたい場合は require_once を使えばよい。include_once や require もあるって? それらは使わなくていい。
なぜかって? それを知るためには、しばし、おっさんの無駄話を聞いてもらわねばなるまい。

スクリプトはまさに台本 - セリフとト書き

本当はウェブアプリに限らない話なんだが、とりあえず、ウェブアプリをスクリプト言語で書くことを考えよう。スクリプト言語っていうのは、script すなわち台本を書くための言語だね。台本には「セリフ」と「ト書き」があるのはいいよね。「セリフ」ってのは役者が喋る言葉で、そのまま台本に書かれたものが観客の耳に届く。「ト書き」ってのは、状況を説明したり、役者の動作を説明したりする文章のこと。役者や裏方さんはそれを読んで解釈して、表現する。観客に届くのは台本に書かれたものじゃなくて、役者や裏方さんが解釈・表現したもの。

で、(PHP じゃない) たいていのスクリプト言語ってのは、ト書きベースなんだね。台本に書いてあるのは、「ああせい」「こうせい」というト書き。観客への表現は「『〜』と言う」みたいに、『』でセリフを示した動作として書かれる。 print とか echo とか、そういう名前の動作命令なわけ。ト書きの中にセリフが散りばめられるからト書きベース。

それに対して、PHP ってのはセリフベースなんだ。台本には直接セリフが書いてある。台本に「こんにちは」と書いてあったら役者は「こんにちは」と言い、「こんにちは、と言う」と書いてあったら役者は「こんにちは、と言う」と言う。ト書きベースだとやるべき動作が書いてあったのに比べて、喋るべきセリフが直接書かれているのが違う。print だの echo だのを使わなくても、直接セリフを書けばいいんだから楽だよね。こういうセリフベースの言語には PHP の他にも、JSPASP やなんかがあるよ。テンプレートエンジンがどうとかっていうのも仲間と考えていいけど、まあ、それは置いとこう。

ウェブアプリで言うと観客に届く表現というのは、まあ HTML だと言ってもいいから「セリフ」は「HTML」って言ってもいい。「ト書き」は「プログラム」って言ってもいい。

セリフベース言語でト書きを書くには

もし、セリフベースの言語で一切ト書きが書けなかったら、それはいつ、どこで上演してもまったく内容が同じ台本しか書けないことになる。でも、客層や時間帯、上演場所、役者の個性なんかによってアレンジされるのも楽しいよね。

ということで、セリフベースの言語は「こっからここまでト書きです」というふうに明示してト書きが書けるようになっている。PHP で言えば、<?php と ?> で囲んだところがト書きになる。<?php があると、そこからト書きベースモードに入り、?> があるとセリフベースモードに戻る、って考えてもいい。ともかく、ト書きベースになっているところは、元からト書きベースの言語と同じで、そこに書くべきは「ああせい」「こうせい」という動作であって、表現される内容そのものじゃない。

セリフベース言語でト書きベースモードになっているとき、print だの echo だのの発言命令を使って「セリフを書く」ことができたりする。ここを混乱する人がたまにいるみたいだけど、違いはわかったかな。ここ重要ね。

さて include, require

ここまで書いたら察しのいい人はもうわかったかもしれないね。include ってのは「セリフベース」の命令で、require ってのは「ト書きベース」の命令なんだ。

include は HTML 的に考えて、「ここにこのファイルに書いておいた別の HTML を差し込む」ってことを示すものなわけ。include = 差込み、だもんね。使いどころとしては、いろんなページの HTML で共通のヘッダ部分とかフッタ部分とか、メニュー部分とか、そういうものを別ファイルにしておいて、それぞれのページから include で差し込むようにしておく。そうすると、共通部分に変更があった場合に一つのファイルを変更するだけでいいから楽だよね。

一方、require はプログラム的な発想で、これからやることに必要なファイルを require、要求するわけだ。で、要求される側ってのは、要求する側で使う部品とか道具についての定義が書いてあるわけだ。しょっちゅう使う部品とか道具をあちこちのファイルから使えると便利だよね。

これで、おのずと include と require の使いわけができるようになると思うけど、どう? include で差し込まれるファイルは、セリフが書いてあることが想定されるよね。喋ることが求められているんだもん。一方で、require で読み込まれるファイルは部品として使われるものが定義されているんだから、勝手に喋っちゃいけないよね。喋るってのは HTML を出力するってことね。

さて include_once, require_once

include_once や require_once ってのは、何回 include, require されても、最初の一回しか有効にならないよってこと。

でもさ、考えてみてよ。差込み表示したくて何回か include するのに、最初の一回しか表示されないって変じゃない? include_once があっても、そこに差し込まれるかどうかわからないってことだよ。変なの。なので、include_once ってのは使いどころがないって思うわけ。include があったら、そこに差し込まれる HTML があるんだな、って理解したほうがあとから台本を読み返したときもわかりやすいじゃない。

require の方は、部品や道具の読込みなわけだ。これは一回どこかで require して取り込んであれば、別のところで require して再度取り込む必要はないわけだ。require してあるところで毎回取り込んでいると無駄ってこと。require_once ってのは言い換えると、「ほかのどなたがすでに取り込んでいるならそれを使わせていただきますが、そうでなければここで自分で取り込んでから使います」で、require ってのは「ほかのだれかが取り込んでいようがいまいが、俺はこれを使うからここで取り込んで使うぜ」なのね。てことは、常に require_once 使ってたほうが無駄がないじゃない。ってことで、require を使う積極的な理由はほとんどないんじゃないって思うわけさ。

そこが PHPPHP らしいところ

私の考えとしては、include_once、require は不要。どうせだったら、PHP の require_once の機能を require という名前にしちゃえばよかったのにと思う。require したら、「ほかのどなたがすでに取り込んでいるならそれを使わせていただきますが、そうでなければここで自分で取り込んでから使います」と理解すればいいってことね。

ま、それがそうなっていないのが PHP らしいところなんだけどね。