【PHP】includeの使い方、クラスをincludeした時の動きを検証
-
カテゴリ:
- PHP
前回の「includeとinclude_onceの違い」の記事では、PHPで良く使用されるincludeとinclude_onceの動きの違いについて書きました。
今回はその流れで、include自体の動きをもっと知るために。クラスをincludeしてみたいと思います。
クラスのinclude
下記の例はシンプルにクラスをincludeしています。
Humanクラスは「名前($name)」と「hello()」という振る舞いと持っているクラスで、メソッドが何回呼ばれたかわかるように「カウンター($counter)」を持っています。
Human1.php
<?php_
echo "[Humam1クラス] start\r\n";
class Human1 {
public $name;
public $counter=0;
function __construct($name) {
echo "{$name}がコンストラクタ実行\r\n";
$this->name = $name;
}
function hello() {
$this->counter += 1;
echo "こんにちは{$this->name}です。({".$this->counter."回目)\r\n";
}
}
echo "[Humam1クラス] end";
test1-1.php
<?php
include('Human1.php');
$h = new Human1('テスト1');
$h->hello();
実行結果
$ php test1-1.php
# 出力結果
#[Humam1クラス] start
#[Humam1クラス] end
#テスト1がコンストラクタ実行
#こんにちはテスト1です。({1回目)
純粋なPHPのスクリプトをincludeした際は、そのタイミングでソースが読み込まれechoなどのコンソールに出力する処理もすべて処理されていました。
しかしクラスの場合は、上から順番に読み込まれますがクラスの中の処理は実行されません。
インスタンスを作成してメソッドを呼ぶことで初めて実行されます。
次に、途中で複数インスタンスを作って実行してみます。
test1-2.php
<?php
include('Human1.php');
$h = new Human1('テスト1');
$h->hello();
// 別のインスタンスを作成
$h1 = new Human1('テスト2');
$h1->hello();
$h->hello();
実行結果
$ php test-1-2.php
# 出力結果
#[Humam1クラス] start
#[Humam1クラス] end
#テスト1がコンストラクタ実行
#こんにちはテスト1です。({1回目)
#テスト2がコンストラクタ実行
#こんにちはテスト2です。({1回目)
#こんにちはテスト1です。({2回目)
$hと$h1はそれぞれ別のインスタンスであるため、その中に保持しているカウンター($counter)も別々でカウントされていきます。
<?php
include('Human1.php');
$h = new Human1('テスト1');
$h->hello();
echo $h->counter."\r\n";
// 再度includek
include('Human1.php');
$h1 = new Human1('テスト2');
$h1->hello();
$h->hello();
実行結果
$ php test1-3.php
# 出力結果
#[Humam1クラス] start
#[Humam1クラス] end
#テスト1がコンストラクタ実行
#こんにちはテスト1です。({1回目)
#1
#[Humam1クラス] start
#
#Fatal error: Cannot declare class Human1, because the name is already in use in Human1.php on line 4
Human1.phpの4行目、「class Human1 {」のところでエラーになりました。
つまりincludeして同じクラスファイル名が登場したタイミングでエラーになります。
同じクラスは複数includeできないということですね。
staticを含むクラスのinclude
staticを含むクラスのincldeを試してみます。
static変数とは、簡単いうと以下のような性質を持ちます。
- インスタンスを作成しなくても、includeした段階から使用できる
- PHPの1つの処理の中で、1つしか存在できない
使用用途とはいろいろあるかと思いますが、よくシングルトンパターンを使う際に見かけます。
Human2.php
<?php_
echo "[Humam2クラス] start\r\n";
class Human2 {
public $name;
public static $counter=0; // static変数
function __construct($name) {
echo "{$name}がコンストラクタ実行\r\n";
$this->name = $name;
}
function hello() {
Human2::$counter += 1;
echo "こんにちは{$this->name}です。({".Human2::$counter."回目)\r\n";
}
}
echo "[Humam2クラス] end\r\n";
test2-1.php
<?php
include('Human2.php');
// ↓staticはインスタンスを作成しなくても使用できる
echo Human2::$counter."\r\n";
$h = new Human2('テスト1');
$h->hello();
echo Human2::$counter."\r\n";
実行結果
$ php test2-1.php
# 出力結果
#[Humam2クラス] start
#[Humam2クラス] end
#0
#テスト1がコンストラクタ実行
#こんにちはテスト1です。({1回目)
#1
「Human2::$counter」はstatic変数にアクセスする方法です。
インスタンスを作成される前に$counterをコンソールに出力して、「0」が取得できているかと思います。
次に、処理途中で別インスタンスを作成してみます。
<?php
include('Human2.php');
// ↓staticはインスタンスを作成しなくても使用できる
echo Human2::$counter."\r\n";
$h = new Human2('テスト1');
$h->hello();
echo Human2::$counter."\r\n";
// 別のインスタンスを作成
$h1 = new Human2('テスト2');
$h1->hello();
$h->hello();
実行結果
$ php test2-2.php
# 出力結果
#[Humam2クラス] start
#[Humam2クラス] end
#0
#テスト1がコンストラクタ実行
#こんにちはテスト1です。({1回目)
#1
#テスト2がコンストラクタ実行
#こんにちはテスト2です。({2回目)
#こんにちはテスト1です。({3回目)
上記結果の通り、$hと$h1は別インスタンスですが、static変数である$counterは共通してカウントされているのが分かるかと思います。
まとめ
今回includeの動きを掘り下げるために、クラスを読み込んだ時の動きを検証してみました。
概ね自分の予想通りな動きをしていたので、これからは自信を持って使っていけると思います。
がしかし、周りからの噂で聞いたのですが、最近のは流行はincludeやreqireを使わず、namespace(名前空間)なるものを使うらしいです。^^;
ちょっと気になるので、次はnamespaceについて勉強して記事にしたいと思います。