ここまではclass.phpとinherit.phpという2つのファイルに分けて、サンプルコードを記述してきた。これら2つのファイルで定義されているクラス群を(クラス定義以降のテストコードは削除するものとして)別のファイルから再利用したいとしよう。もちろん、ここで懸念されるのはクラス名の衝突だ。そして、その回避策となるのは、もちろん名前空間である。
名前空間の定義にはnamespaceキーワードを使用する。例えば、class.phpファイルの内容を次のように変更する。
<?php
namespace Cls;
class Foo
{
public $name;
private $id;
static private $count = 0;
public function showProp()
{
echo "id: " . $this->id . ", name: " . $this->name . PHP_EOL;
}
static function showCount()
{
echo "number of instance(s): " . self::$count . PHP_EOL;
}
public function __construct($name = "no name")
{
$this->name = $name;
$this->id = self::$count;
static::$count++;
}
}
また、inherit.phpファイルは次のように修正する。
<?php
namespace Inherit;
class Foo
{
private $m;
private static $cls = "Foo";
public function __construct($m = "Foo")
{
$this->m = $m;
}
public function Hello($msg = "Hello")
{
echo $msg . " " . $this->m . PHP_EOL;
}
public static function StaticHello()
{
echo "Hello from class " . static::$cls . PHP_EOL;
}
}
class Bar extends Foo
{
private $n;
protected static $cls = "Bar";
public function __construct($m = "Foo", $n = "Bar")
{
parent::__construct($m);
$this->n = $n;
}
public function Hello($msg)
{
parent::Hello($msg);
echo $msg . " " . $this->n . PHP_EOL;
}
}
class Baz extends Foo
{
protected static $cls = "Baz";
}
namespaceキーワードによる名前空間の定義はファイルの先頭に記述する(実際には単一ファイル内で複数の名前空間を定義できる。「同一ファイル内での複数の名前空間の定義」を参照)。これ以降、class.phpファイルとinherit.phpファイルで定義されているクラスFooはそれぞれ\Cls\Foo、\Inherit\Fooのようにして参照できるようになる。先頭の「\」はトップレベルの名前空間を意味する。先頭に「\」がないときには、現在の名前空間からの相対参照となる。が、以下のコードでは「Cls\Foo」などのようにトップレベルの「\」を省略する。
2つのファイルを別ファイルで読み込み、再利用するには、require、require_once、include、include_onceが使用できる。requireとrequire_onceは、指定されたファイルの読み込みに失敗するとエラーが発生する。includeとinclude_onceは失敗したときに警告を発行するという違いがある。また、末尾に「_once」があるものは、既に該当ファイルが読み込まれているかをPHPがチェックして、複数回の読み込みを行わないようにしてくれる。ここでは、requireを使用して、namespace.phpファイルで上の2つを使用してみる。
<?php
require "class.php";
require "inherit.php";
$f = new Cls\Foo();
$f->showProp();
$f2 = new Inherit\Foo();
$f2->Hello();
上でも述べたように「Cls\Foo」「Inherit\Foo」のようにして(あるいは「\Cls\Foo」「\Inherit\Foo」のようにして)、それぞれのファイルで定義されているクラスを利用できていることが分かるはずだ。ただし、名前空間名を毎回毎回記述するのは面倒くさい。C#のusingディレクティブがあると便利だ。PHPではこれに相当することをuse演算子で行える。以下に例を示す。
<?php
require "class.php";
require "inherit.php";
use Cls\Foo; // Cls\Fooクラスのインポート
use Inherit\Foo as Foo2; // Inherit\FooクラスをFoo2クラスとしてインポート
$f = new Foo();
$f->showProp();
$f2 = new Foo2();
$f2->Hello();
$b = new Bar();
$b->Hello("Goodbye");
上の2つのuseはCls名前空間とInherit名前空間に含まれている2つのFooクラスをインポートする例だ。以降は、クラスCls\FooはFooとして、クラスInherit\FooはFoo2として利用できる。また、名前空間が多段にネストしている場合には、名前空間のエイリアスを作成することも可能だ。例えば、inherit.phpファイルの名前空間定義を「namespace Sample\Inherit」のように定義していたとしよう。この場合に、エイリアスを作成する例を以下に示す。
<?php
require "class.php";
require "inherit.php";
use Cls\Foo;
use Sample\Inherit as Inherit; // 名前空間のエイリアス
$f = new Foo();
$f->showProp();
$f2 = new Inherit\Foo(); // エイリアスを使用してSample\Inherit\Fooクラスにアクセス
$f2->Hello();
ここでは取り上げないが、名前空間内で定義されている関数や定数もuse演算子でインポートできる。詳細については「名前空間の使用法: エイリアス/インポート」を参照されたい。
本稿では、PHPにおけるクラスの作成方法の基本と、プロジェクトが複数ファイルで構成される場合に必要となる名前空間の基礎、ファイルの読み込みについて見た。例外処理など、他にも覚えておくべきことはあると思われるが、それらについては、次回以降で必要となった時点で紹介していくことにしよう。
Copyright© Digital Advantage Corp. All Rights Reserved.