PHP入門 オブジェクト指向 名前空間

名前空間とは、クラスや関数の苗字や所属のようなものです。たくさんのクラスや関数を定義すると、名前が思わないところで衝突することがあります。そのような場合、従来であれば名前そのものを長くする方法しかありませんでした。名前空間を使えば、クラス名はかなりシンプルなものにすることができます。

名前空間の基本

名前空間を定義するのは、namespace命令です。

構文:namespace命令

namespace 名前空間名

例:

<?php
namespace kc\testphp;
class MyClass{
    //現在のクラス名を表示するための静的メソッドshowClass
    public static function showClass() : void {
        print __CLASS__;
    }
}

名前空間は、ファイルシステムのように階層構造を表現することもできます。その場合、階層の区切りは「\」(バックスラッシュ)で表現します。階層構造のない「namespace kc;」のような名前空間でもかまいませんが、大規模なアプリケーションでは階層を付けておいた方が名前の衝突が起こりづらいです。

__CLASS__で、名前空間を含めた現在のクラスの完全修飾名を取得できます。CLASSの前後のアンダースコア(_)は、それぞれ2つずつです。__CLASS__は、PHPであらかじめ用意されている定数です。

名前空間を利用する場合の注意点

1、名前空間はファイルの先頭で定義すること

ファイルの先頭、とは、namespace命令の前に「?php」以外の何も存在してはなりません。<?phpの外にあるタグや空白文字なども不可です。

2、フォルダー構造は名前空間の階層に準ずること

たとえば、kc\test名前空間に属するMyClassクラスであれば、/kc/testフォルダーに配置します。

これは構文規則ではありません。ルール通りにしなくてもエラーにはなりません。

3、1つのファイルは1つの名前空間に

構文規則上は1つのファイルに複数の名前空間を定義してもかまいません。

<?php
namespace kc {
・・・中略・・・
}
namespace phptest{
・・・中略・・・
}

このように、名前空間に含まれるコードを{}で囲みます。2つ目以降のnamespace命令はファイルの途中にあってもかまいません。ただし、1つのファイルの中で複数の名前空間を定義するのは、コードを読みづらくする原因でもあります。

明示的に名前空間を宣言しないコードは、グローバル名前空間というトップ階層の名前空間に属するとみなされます。

名前の記法の名前解決のルール

名前空間を利用する場合、名前の表記は非修飾名、修飾名、完全修飾名に分類できます。

1、非修飾名

非修飾名は名前空間を含まないなまです。「Person」「MyMail」のような名前のことを言います。次のようにMyClassクラスも非修飾名を使って呼び出すことができます。

<?php
namespace kec\testphp;
require_once 'MyClass.php';
print MyClass::showClass();
関数名だけは例外です。非修飾名で指定された関数が現在の名前空間に存在しない場合、自動的にグローバル名前空間に属する関数名とみなされます。

2、修飾名

修飾名は、名前空間の階層区切り文字を含んだ名前のことで、例えば「chap1\MyClass」のうような名前です。この場合も、名前は現在の名前空間を基点に解釈されます。たとえば、現在の名前空間がkc\test名前空間であれば、修飾名chap1\MyClassは、kc\test\chap1\MyClassと見なされます。

<?php
namespace kec\testphp;
require_once 'chap1/MyClass.php';
print chap1\MyClass::showClass(); //結果:kc\test\chap1\MyClass

3、完全修飾名

完全修飾名は、「\」で始まる修飾名のことで、たとえば\kc\test\chap1\MyClassのようなものです。この場合、その名前は現在の名前空間に関わらず、\kc\test\chap1\MyClassとみなされます。

<?php
require_once 'kc/test/chap1/MyClass.php';
print \kc\test\chap1\MyClass::showClass(); //結果:kc\test\chap1\MyClass

インポート

名前空間という概念が導入されても、結局、クラスを呼び出すときには「kc\test\MyClass」のような長い名前を使わなければなりません。それでは、メリットがあまり感じられません。そこで、登場するのが、use命令による型のインポートです。

クラスのインポート

use命令の最も基本的な記法です。

<?php
require_once './kc/test/MyClass.php'
require_once './kc/test/MyClass2.php'
require_once './kc/test/MyClass3.php'

//MyClassクラスをインポート(showClassは現在の完全クラス名を表示)
use kc\test\MyClass;  //➊
print MyClass::showClass(); //結果:kc\test\MyClass

use kc\test\MyClass2,kc\test\MyClass3 //➋
print MyClass2::showClass();//結果:kc\test\MyClass2
print MyClass3::showClass();//結果:kc\test\MyClass3

❶のように単一のクラスをインポートできるのはもちろん、❷のように、カンマ区切りで複数のクラスをまとめてインポートすることも可能です。もっとも、❷のように同一の名前空間から複数のクラスをインポートするために、いちいち完全修飾名で列記するのが面倒な場合は、次のようにグループ化することもできます。

use kc\test\{MyClass2,MyClass3};

use命令の注意点

use命令によるインポートですが、いくつか注意点があります。

1、グローバルスコープ、またはnamespaceブロックの配下で呼び出す。

use命令はコンパイルのタイミングでインポートを実行します。よって、class/functionはじめ、制御構文ブロックの配下で呼び出すことはできません。

2、インポートの有効範囲はファイル単位

use命令によるインポートは、現在のファイルでのみ認識されます。例えば、require_once ‘included.php’のようなインクルードファイル先では認識しない

定数/関数のインポート

use const/use function命令を利用することで、定数/関数をインポートすることも可能です。

/kc/test/MyUtil.php

<?php
namespace kc\test;
const AUTHOR = '山田太郎';
function myFunc(){
  return 'こんにちわ、PHP';
}
<?php
require_once './kc/test/MyUtil.php';

use const kc\test\AUTHOR;
print AUTHOR;
use function kc\test\myFunc;
print myFunc();

名前空間までをインポートする

use kc
print test\AUTHOR;
print test\myFunc();

名前競合時に別名を設定する

扱うライブラリが増えてくると、名前空間を跨いで名前が競合することがあります。そのような状況では、use命令にas句を付与することで、クラス/関数に別名(エイリアス)を付与することもできます。

<?php
require_once './kc/test/MyClass.php'
require_once './kc/test/sub/MyClass.php'

use kc\test\MyClass;
use kc\test\sub\MyClass as SubClass;

print MyClass::showClass();//結果:kc\test\MyClass
print SubClass::showClass();//結果:kc\test\sub\MyClass