Help us understand the problem. What is going on with this article?

【PHP超入門】名前空間(namespace・use)について

はじめに

Webアプリケーションを作るときに名前空間という機能がよく利用されています。
便利な機能なので、理解しておきましょう。

この記事は、関数ぐらいまでの知識がある方が対象です。
クラスの基礎(プロパティやメソッド)知識があると尚よいです。
クラスのプロパティやメソッドについて理解していない方は、下記の該当箇所をご覧ください。

今回、名前空間について学ぶために

という流れでまとめました。

今回は、下記のローカル環境で動作確認しています。

OS XAMPP Apache PHP
Windows10 5.6.24 2.4.23 5.6.24

私自身、未熟ですので説明に誤りがあるかもしれません。
そのときは、ご指摘ください((_ _ (´ω` )ペコ

PHPは同じ名前の関数は定義できない?

本当に同じ名前の関数が定義できないのか確かめてみましょう。

sato.phpsuzuki.php の2つのファイルで同名の getGreeting()という挨拶を返してくれる関数を定義します。

sato.php
<?php
function getGreeting() {
    return 'おはよう';
}
suzuki.php
<?php
function getGreeting() {
    return 'こんばんは';
}

call.php から2つのファイルを読み込み、getGreeting() 関数を呼びましょう。

call.php
<?php
require_once 'sato.php';
require_once 'suzuki.php';

echo getGreeting();

sato.phpgetGreeting() なら おはよう と表示され、suzuki.phpgetGreeting() なら こんばんは と表示されるはずですが、エラーが表示されました。

エラー
Fatal error: Cannot redeclare getGreeting() (previously declared in C:\xampp\htdocs\suzuki.php:3) in C:\xampp\htdocs\sato.php on line 4

Fatal error は致命的なエラーという意味で、redeclarere- +‎ declare という英語で declare は宣言という意味ですので、Cannot redeclare getGreeting()getGreeting()関数を再度宣言することはできませんという意味になります。

ご覧の通り、同じ関数名を使うことはできません。
別の関数名にすれば問題は解決できますが、定義する関数が多くなると名前の衝突を避けるために冗長な名前にしなければなりません。
また、複数人で各々がコードを書いて、それぞれのコードを読み込んだときに名前が衝突する可能性もあります。
名前空間を使うことで、この問題を解決できます。

名前空間を定義する

名前空間とは、文字通り名前の空間のことで、ここからここまでのコードが○○という空間に属していると定めることができます。
空間が違えば、同じ関数名を定義して使うことができます。
名前空間という仕組みは、PHP5.3.0で導入されました。

名前空間を定義するには、namespaceキーワードの後に任意の空間名を記述します。

名前空間を定義する構文
namespace 名前空間名;

この namespace の記述ですが、今は関数を定義する方に記述します。
先ほどの例で言えば、sato.php または suzuki.php に記述します。

また、namespace は、最初に記述してください。

OK:namespaceは最初に記述する
<?php
namespace test;

namespaceの前にphpの命令文やHTMLなどを記述するとエラーが表示されます。
namespaceより前に書くことが許されているコードは declare(ディクレア)文のみです。

NG:namespaceの前にはphpの命令文を記述しない
<?php
require_once 'test.php';
namespace test;
NG:namespaceの前にはHTMLを記述しない
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<?php
namespace test;
?>
</body>
</html>

次は、名前空間に属する関数を利用する方法を見ていきましょう。

名前空間に属する関数を利用するには?

名前空間に属する関数を呼ぶときは、○○の名前空間にある関数だよと記述する必要があります。
最初に名前空間名を記述した後に \ (バックスラッシュ)を記述し、その後に関数名を記述します。
バックスラッシュは、円記号で入力できます。
環境によっては、バックスラッシュではなく、円記号で表示されますが、円記号のままで問題ありません。

名前空間に属する関数を利用する構文
名前空間名\関数名;

先ほどの例でいえば、call.php で関数を利用するときに上述したように記述します。

今まで同名の関数は定義できないと言ってきましたが、下記も同様です。

  • 関数
  • クラス
  • インターフェイス
  • 定数(constで定義)

これらも名前空間を利用することで、名前の衝突を避けることができます。
逆に言えば上述した4つ以外は、名前空間の影響を受けません。
今回は関数を例にしていますが、主にクラス名の衝突を避けるために名前空間が用いられることが多いです。

名前空間に属するクラスを利用する場合は、先ほどの関数名をクラス名にするだけです。

名前空間に属するクラスを利用する構文
名前空間名\クラス名;

ちなみにPHPで定数を定義するには、 constキーワードとdefine関数を使う2種類の方法があります。
名前空間の影響を受けるのは、constキーワードのみで、define関数は影響を受けません。

次は、名前空間を利用してみましょう。

実際に名前空間を利用してみる

最初にエラーが発生した sato.phpsuzuki.php で名前空間を定義してみましょう。
sato.phpnamespace sato; を追記します。

sato.php
<?php
namespace sato;

function getGreeting() {
    return 'おはよう';
}

今度は、suzuki.phpnamespace suzuki; を追加しましょう。

suzuki.php
<?php
namespace suzuki;

function getGreeting() {
    return 'こんばんは';
}

call.php では sato\getGreeting(); として関数を利用します。

call.php
<?php
require_once 'sato.php';
require_once 'suzuki.php';

echo sato\getGreeting();

これで、satoという名前空間にあるgetGreeting()関数が呼ばれ おはよう と表示されます。
sato\getGreeting(); を、suzuki\getGreeting(); に変更すれば、こんばんは と表示されます。

今回、名前空間名をファイル名と同じく命名しましたが、名前空間名は任意で決められますので、ファイル名と関係ない名前空間名にすることも可能です。
ただ、全く関係がない名前空間名にするとわかりにくいので、ファイル名と同じくするなどわかりやすい名前空間名にしてください。

一つのファイルに複数の名前空間を記述できるの?

先ほどは、一つのファイルに一つの名前空間を定義しましたが、一つのファイルに複数の名前空間を定義することが可能です。
複数の名前空間を定義するには、2つの方法があります。
それぞれの方法を確認しましょう。

No.1 名前空間を続けて記述する方法

function.php
<?php

namespace takahashi;

function getGreeting() {
    return 'ごきげんよう';
}

namespace tanaka;

function getGreeting() {
    return 'Hello';
}

namespaceで名前空間を宣言した後に記述した関数などは、その名前空間に属します。
その後にまた namespace で名前空間を宣言すれば、その名前空間に属します。
先ほどの記述は、下記のような名前空間になります。

namespace1.png

call.php で関数を呼ぶときに適切に名前空間名を記述すれば、それぞれの関数を呼ぶことができます。

call.php
<?php
require_once 'function.php';

echo takahashi\getGreeting();
echo tanaka\getGreeting();

実行すると ごきげんようHello が表示されます。

名前空間を続けて記述する方法を紹介しましたが、この方法は、どこまでがどの名前空間かわかりにくいので推奨されません。
もう一つの方法も見ていきましょう。

No.2 波括弧で囲む方法

波括弧で囲むことで名前空間を定義することが可能です。
波括弧内に記述した関数などは、その名前空間に属します。

function.php
<?php

namespace takahashi {
    function getGreeting() {
        return 'ごきげんよう';
    }
}

namespace tanaka {
    function getGreeting() {
        return 'Hello';
    }
}

下記のような名前空間になります。

namespace2.png

先ほどと同様に call.php で名前空間を含めて関数を記述すれば、それぞれの関数を呼ぶことができます。

call.php
<?php
require_once 'function.php';

echo takahashi\getGreeting();
echo tanaka\getGreeting();

実行すると ごきげんようHello が表示されます。

波括弧を使って複数の名前空間を定義する方法を紹介しました。
先ほどの方法より、わかりやすくなっていますが、なるべく一つのファイルでは一つの名前空間にするのがわかりやすいです。

波括弧を使って複数の名前空間を定義する方法を紹介しましたが、名前空間の外(波括弧の外)に命令文を記述できるのか確かめてみましょう。

名前空間の外にも命令文を記述できるの?

名前空間の外にも、命令文を記述できるのか確かめてみましょう。
先ほどの記述の最後に echo 文を追記します。

function.php
<?php

namespace takahashi {
    function getGreeting() {
        return 'ごきげんよう';
    }
}

namespace tanaka {
    function getGreeting() {
        return 'Hello';
    }
}

echo 'ニーハオ';

実行すれば ニーハオと表示されるはずですが、下記のようなエラーが表示されました。

エラー
Fatal error: No code may exist outside of namespace {}

Fatal error は致命的なエラーという意味で、No code may exist outside of namespace は、「コードは名前空間の外に存在してはいけません」というような意味だと思います。
英語がダメな人なので、意訳に誤りがあればご指摘ください。

ご覧のように名前空間の外に命令文を記述することはできませんので気をつけましょう。

名前空間は、複数のファイルで同じ名前空間を宣言することが可能です。
その方法を見ていきましょう。

複数のファイルで同じ名前空間は使えるの?

複数のファイルで同じ名前空間を使えます。
単純に同じ名前空間名の namespace を宣言すれば、同じ名前空間になります。

takahashi.php
<?php
namespace human;
tanaka.php
<?php
namespace human;

takahashi.phptanaka.php は同じ名前空間です。
当たり前ですが、同じ名前空間になるので、同名の関数などは定義できません。

今まで、名前空間名を takahashitanaka などと命名してきましたが、単純なので名前空間名が重複する可能性があります。
サブ名前空間を使うことでもっと自由な命名が可能になります。

サブ名前空間って何?

名前空間は、ディレクトリ構造の概念と同じく階層を持たせて記述することが可能です。
\ で区切ってサブ名前空間を記述できます。

サブ名前空間の記述例
名前空間\サブ名前空間\サブ名前空間

sato.php の名前空間名をサブ名前空間使って japan\tokyo\chiyoda\sato にしてみましょう。

sato.php
<?php
namespace japan\tokyo\chiyoda\sato;

function getGreeting() {
    return 'おはよう';
}

名前空間に属する関数を利用するには、名前空間名も記述する必要があります。
このときにサブ名前空間も忘れずに記述しましょう。

call.php
<?php
require_once 'sato.php';

echo japan\tokyo\chiyoda\sato\getGreeting();

実行すると おはようと表示されます。

サブ名前空間が使えることで、実際のディレクトリ構造と同じ命名が可能になります。
サブ名前空間も使ってわかりやすい名前空間名を命名するようにしましょう。

先ほど名前空間に属する関数を呼ぶときに japan\tokyo\chiyoda\sato\getGreeting() と記述しました。
実はこの記述の仕方にはいくつか種類があります。

HTMLには画像へのパスを指定するときにルート相対パスやドキュメント相対パスなどの種類があります。
下層フォルダにある画像へアクセスするのか、同ディレクトリにある画像にアクセスするのか、ルートディレクトリから画像へアクセスするのかによって記述の仕方が異なります。

下層フォルダにある画像へアクセスする場合
<img src="images/photo.jpg">
同ディレクトリにある画像へアクセスする場合
<img src="photo.jpg">
ルートディレクトリから画像へアクセスする場合
<img src="/2016/images/photo.jpg">

名前空間も画像のパスと同様に記述の仕方が変わります。
次は、この記述の仕方について見ていきましょう。

名前空間の記述について

今まで関数を呼ぶ側には、名前空間を指定しませんでした。
関数を呼ぶ側にも、namespace を記述することが可能です。

実際に関数を呼ぶ側にも同じ名前空間を宣言して確かめてみましょう。

実際に同じ名前空間を宣言して関数を呼んで確かめる

sato.php の名前空間名を japan\sato にして、getGreeting()関数を記述します。

sato.php
<?php
namespace japan\sato;

function getGreeting() {
    return 'おはよう';
}

call.phpでも同名の名前空間を定義し、echo japan\sato\getGreeting();として関数を呼んでみましょう。

call.php
<?php
namespace japan\sato;

require_once 'sato.php';
echo japan\sato\getGreeting();

実行すると下記のエラーが表示されました。

Fatal error: Call to undefined function japan\sato\japan\sato\getGreeting() in C:\xampp\htdocs\call.php on line 4

Fatal error は致命的なエラーという意味で、Call to undefined functionはコールする関数が未定義ですという意味になります。
注目すべきは次の japan\sato\japan\sato\getGreeting() です。
japan\satoが2回記述されています。

今回、call.phpには同じ名前空間を宣言したので、sato.phpcall.php も同じ名前空間に属します。
ディレクトリ構造で言えば、同ディレクトリにあるのと同じです。
同ディレクトリにあるなら、階層の記述は不要です。
同ディレクトリにもあるにもかかわらず、japan\sato\getGreeting() と記述したため、エラーが表示されました。

echo japan\sato\getGreeting();echo getGreeting(); に変更しましょう。

call.php
<?php
namespace japan\sato;

require_once 'sato.php';
echo getGreeting();

実行すると おはようと表示されます。

このようにディレクトリ構造のように階層によって指定方法が異なります。
名前空間の指定方法には

  • 非修飾形式
  • 修飾形式
  • 完全修飾形式

の3つがあります。どのような形式なのか確認していきましょう。

非修飾形式

ディレクトリ構造で言うところの同ディレクトリ内からの指定になります。

sato.php には tokyo\sato; という名前空間名を定義し、getGreeting()関数を記述します。

sato.php
<?php
namespace tokyo\sato;
function getGreeting() {
    return 'おはよう';
}

call.php には sato.php と同じ名前空間を定義します。
同じ名前空間にあるため、関数を呼ぶときは名前空間を記述しません。

call.php
<?php
namespace tokyo\sato;

require_once 'sato.php';
echo getGreeting();

このように同じ名前空間にあるため、 \ を含まない指定が非修飾形式です。

修飾形式

ディレクトリ構造で言うところのドキュメント相対パスです。

先ほどと同様に sato.php には namespace tokyo\sato; という名前空間名を定義し、getGreeting() 関数を記述します。

sato.php
<?php
namespace tokyo\sato;

function getGreeting() {
    return 'おはよう';
}

call.php には tokyo という名前空間を定義します。
ディレクトリ構造で言うと sato.php の名前空間より一つ上の階層に位置します。
一つ上の階層にあるため、関数を呼ぶときは echo sato\getGreeting(); と記述します。

call.php
<?php
namespace tokyo;

require_once 'sato.php';
echo sato\getGreeting();

このように上位階層にあるため、途中に \ を含めて階層も指定するのが修飾形式です。

完全修飾形式

ディレクトリ構造で言うところのルート相対パスです。

先ほどと同様に sato.php には namespace tokyo\sato; という名前空間名を定義し、getGreeting() 関数を記述します。

sato.php
<?php
namespace tokyo\sato;

function getGreeting() {
    return 'おはよう';
}

関数を呼ぶときに最上位階層から指定するため、call.phpの名前空間はどこでも構いませんが、tokyoとします。
関数を呼ぶときは、最初に \ を記述して最上位階層から指定します。
echo \tokyo\sato\getGreeting(); と記述します。

call.php
<?php
namespace tokyo;

require_once 'sato.php';
echo \tokyo\sato\getGreeting();

このように最初に \ を記述して最上位階層から指定するのが完全修飾形式です。

これで、それぞれの形式について理解できたかと思います。

最初の方では、関数を呼ぶ側には名前空間を定義していません。
この場合は、どのような名前空間になっているのか見ていきましょう。

名前空間を定義しない場合は?

名前空間を定義しないとグローバル名前空間に属します。
ディレクトリ構造で言うところのルートディレクトリです。

先ほど、波括弧を使って複数の名前空間を定義する方法を紹介しました。
このときに namespace の名前空間名を省略すると、グローバル名前空間になります。
下記のように記述した場合、最後の getGreeting() 関数はグローバル名前空間に属します。

function.php
<?php

namespace takahashi {
    function getGreeting() {
        return 'ごきげんよう';
    }
}

namespace tanaka {
    function getGreeting() {
        return 'Hello';
    }
}

namespace {
    function getGreeting() {
        return 'ニーハオ';
    }
}

名前空間を宣言しない場合と、namespaceの名前空間名を省略した場合は、両方ともグローバル名前空間に属するため、下記の2つは同じ名前空間に同じ関数が定義されていることになります。

名前空間を宣言しない
<?php
function getGreeting() {
    return 'ニーハオ';
}
namespaceの名前空間名を省略
<?php
namespace {
    function getGreeting() {
        return 'ニーハオ';
    }
}

これで namespace の記述については、一通り理解できたかと思います。

ただ、名前空間名が japan\tokyo\chiyoda\sato\getGreeting(); のように長いと毎回書くのが大変です。
use キーワード使うことで、このような問題を解決できます。

use キーワードについて

use キーワードを使うことで、名前空間などをインポートしたり、エイリアスを作成することができます。
まずは、インポートとエイリアスの意味について確認しましょう。

エイリアスとは、下記の意味を持つ英単語です。

エイリアスとは、偽名、別名、通称などの意味を持つ英単語。

引用:エイリアスとは : IT用語辞典

インポートとは、下記の意味を持つ英単語です。

インポートとは、取り込む、取り込み、持ち込む、持ち込み、運び込む、輸入(する)、移入(する)などの意味を持つ英単語。

引用:インポートとは : IT用語辞典

use キーワードを使うことで、名前空間の記述を短くした別名または同名を作ることが可能です。
別名の場合はエイリアスと呼び、同名の場合はインポートと呼びます。
今の段階では「名前空間の記述を短くした別名または同名」というのがイメージできないと思いますが、今のところはエイリアスとインポートの定義だけ覚えておきましょう。

use キーワードを使うことで、具体的には下記のことが可能です。

  • 名前空間などのエイリアス(別名)を作成
  • 名前空間の全て、または一部をインポート
  • クラスをインポート
  • 関数をインポート
  • 定数をインポート

それぞれの方法を確認していきましょう。

名前空間などのエイリアス(別名)を作成

use キーワードと as キーワードを組み合わせて名前空間のエイリアス(別名)を作成することが可能です。
エイリアスを作成するには、下記のように記述します。

名前空間の別名(エイリアス)を作成
use 名前空間の全て、または一部 as 別名;

use の後に記述する名前空間は完全修飾形式で記述してください。
これはエイリアスを作成するときだけではなく、useキーワードで記述するときの決まりごとです。
完全修飾形式は、先頭に\ を付ける必要がありますが、use に記述する名前空間は完全修飾形式として扱われるため、先頭の \ は不要です。
use キーワードでは、先頭の \ は付けないでください。

実際に名前空間のエイリアスを作成してみましょう。

tokyo.php には asia\japan\kanto\tokyo という名前空間を定義して、クラス内に getPref()メソッドを定義します。
getPref()メソッドを呼ぶと tokyo と表示されます。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

class pref {
    public function getPref() {
        return 'tokyo';
    }
}

call.php では use を使ってエイリアスを作成します。
use asia\japan\kanto as area; と記述することで、area というエイリアスが作成されます。
これ以降、area と記述すれば、asia\japan\kanto として扱われます。
次の行では、area\tokyo\pref; としてエイリアスを利用します。

call.php
<?php
require_once 'tokyo.php';

use asia\japan\kanto as area;

$a = new area\tokyo\pref;
echo $a->getPref();

実行すると tokyo と表示されます。

今回は、名前空間のエイリアスを作成しましたが、関数、クラス、インターフェイス、定数のエイリアスを作成することも可能です。
先ほどは as キーワードを使ってエイリアスを作成しました。
as キーワードを省略すると、一番右にある非修飾名でインポートすることができます。
次はインポートする方法を見ていきましょう。

名前空間の全て、または一部をインポート

名前空間の全て、または一部をインポートします。
use の後にインポートしたい名前空間の全て、または一部を記述してください。

名前空間もしくは一部をインポート
use 完全修形式の名前空間または一部;

実際に確かめてみましょう。

tokyo.phpは先ほどと同じ記述です。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

class pref {
    public function getPref() {
        return 'tokyo';
    }
}

call.php では use asia\japan\kanto; と記述することで、名前空間の一部をインポートします。
一番右にある非修飾名の kanto でインポートしています。
先ほどの asキーワードを使って表すなら use asia\japan\kanto as kanto と同じ意味です。
今回は別名ではなく、同名ですので、名前空間の一部をインポートしています。

call.php
<?php
require_once 'tokyo.php';

use asia\japan\kanto;

$a = new kanto\tokyo\pref;
echo $a->getPref();

実行すると tokyo と表示されました。

次はクラスをインポートする方法見ていきましょう。

クラスをインポート

先ほどの名前空間をインポートする方法と、ほぼ同じですが use の後に先頭の \ を除いた完全修飾形式で記述したクラス名を記述してください。

クラスをインポート
use 完全修飾形式のクラス名;

実際に確かめてみましょう。

tokyo.phpは先ほどと同じ記述です。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

class pref {
    public function getPref() {
        return 'tokyo';
    }
}

call.phpでは use asia\japan\kanto\tokyo\pref; と記述することで、クラスをインポートします。
一番右にある非修飾名の pref でインポートしています。

call.php
<?php
require_once 'tokyo.php';

use asia\japan\kanto\tokyo\pref;

$b = new pref;
echo $b->getPref();

実行すると tokyo と表示されました。

インポートするときに、use と何回も記述するのは手間がかかります。
まとめてインポートすることも可能です。

クラスをまとめてインポート(カンマ区切り)

, 区切りで記述すれば、まとめてインポートできます。

クラスをまとめてインポート
use 完全修飾形式のクラス名, 完全修飾形式のクラス名;
記述例:クラスをまとめてインポート
use asia\japan\kanto\tokyo\pref, asia\japan\kanto\tokyo\bird, asia\japan\kanto\tokyo\flower;

例としてクラスを用いていますが、名前空間でも関数でも定数でも同様にまとめてインポートできます。
まとめてインポートできましたが、毎回長い修飾名を書くのは手間です。
PHP7.0.0から {} を使って、より簡単にまとめてインポートすることができるようになりました。
その方法を確認しましょう。

クラスをまとめてインポート(波括弧・カンマ区切り)

{} 内に , 区切りで記述することで、まとめてインポートできます。

クラスをまとめてインポート(PHP7.0.0から)
use 完全修飾形式{クラス名, クラス名};
記述例:クラスをまとめてインポート(PHP7.0.0から)
use asia\japan\kanto\tokyo\{
    pref, bird, flower
};
記述例:クラスをまとめてインポート(PHP7.0.0から)
use asia\japan\kanto\{
    tokyo\pref, 
    chiba\bird,
    kanagawa\flower
};

こちらも例としてクラスを用いていますが、名前空間でも関数でも定数でも同様にまとめてインポートできます。
PHP5.6.0から関数のインポートができるようになりました。
その方法を確認しましょう。

関数をインポート

関数をインポートするときは、use functionの後に先頭の \ を除いた完全修飾形式で関数名を記述してください。

関数をインポート(PHP5.6.0から)
use function 完全修飾形式の関数名;

実際に確かめてみましょう。

tokyo.phpasia\japan\kanto\tokyo という名前空間を定義します。
その後に getFlower() 関数を記述します。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

function getFlower() {
    return 'someiyoshino';
}

call.php では、use function asia\japan\kanto\tokyo\getFlower; として関数をインポートします。

call.php
<?php
require_once 'tokyo.php';
use function asia\japan\kanto\tokyo\getFlower;

echo getFlower();

実行するとsomeiyoshinoと表示されます。
PHP5.6.0より前のバージョンでは、関数をインポートすることはできませんので、最初で紹介した名前空間をインポートする方法を利用すれば、短く記述することができます。

PHP5.6.0から定数をインポートができるようになりました。
その方法を確認しましょう。

定数をインポート

定数をインポートするときは、use constの後に先頭の \ を除いた完全修飾形式で定数名を記述します。

定数をインポート(PHP5.6.0から)
use const 完全修飾形式の定数名;

tokyo.phpasia\japan\kanto\tokyo という名前空間を定義します。
WOOD 定数を定義します。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

const WOOD = 'icho';

call.phpでは、use const asia\japan\kanto\tokyo\WOOD;として定数をインポートします。

call.php
<?php
require_once 'tokyo.php';
use const asia\japan\kanto\tokyo\WOOD;

echo WOOD;

実行するとichoと表示されます。
PHP5.6.0より前のバージョンでは、関数と同様に名前空間をインポートする方法を利用すれば、短く記述することができます。

これでインポートとエイリアスを作成する方法について理解できたかと思います。
今までインポート・エイリアスは、同じファイルの同じ名前空間から利用しました。
別の名前空間から利用できるのか、別のファイルから利用できるのか有効範囲を確認しましょう。

インポート・エイリアスの有効範囲

use キーワードを使ってインポートまたはエイリアスを作成したものが、どこから利用できるのか有効範囲を確認してみましょう。
インポート・エイリアスを利用する場合、下記のパターンが考えられます。

  • 同ファイルの同じ名前空間からインポート・エイリアスを利用
  • 同ファイルの別の名前空間からインポート・エイリアスを利用
  • 別ファイルの同じ名前空間からインポート・エイリアスを利用
  • 別ファイルの別の名前空間からインポート・エイリアスを利用

先ほどの例では、同ファイルの同じ名前空間内から利用できたので、最初のパターンは問題ありません。
他のパターンを確認しましょう。

同ファイルの別の名前空間からインポート・エイリアスを利用

tokyo.php に名前空間を定義して、pref クラスと bird クラスを定義します。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

/* prefクラスの定義 */
class pref {
    public function getPref() {
        return 'tokyo';
    }
}

/* birdクラスの定義 */
class bird {
    public function getBird() {
        return 'yurikamome';
    }
}

call.php では、a という名前空間でインポートとエイリアスを作成します。
b という別の名前空間からインポートとエイリアスを利用してみます。

call.php
<?php

namespace a {

    require_once 'tokyo.php';

    /* 名前空間のインポート */
    use asia\japan\kanto;

    /* birdクラスのエイリアスを作成 */
    use asia\japan\kanto\tokyo\bird as tori;

}

namespace b {

    require_once 'tokyo.php';

    /* インポートを利用 */
    $a = new kanto\tokyo\pref;
    echo $a->getPref();

    /* エイリアスを利用 */
    $b = new tori;
    echo $b->getBird();

}

実行すると、エラーが表示されました。

エラー
Fatal error: Class 'b\kanto\tokyo\pref' not found in C:\xampp\htdocs\call.php on line 20

pref クラスが見つからないと書いてあります。
インポートが機能していません。
インポートを利用した時点でエラーが発生し、それ以降の処理はされていないので、上述したエラー内容だけでは、エイリアスを利用した場合の結果がわかりません。
エイリアスを利用した場合の結果も確かめましたが、同様にクラスが見つからないとのエラーが表示されました。
同ファイルの別の名前空間からインポート・エイリアスを利用できませんでした。

次のパターンも確認しましょう。

別ファイルの同じ名前空間からインポート・エイリアスを利用

tokyo.phpの記述は先ほどと同様です。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

/* prefクラスの定義 */
class pref {
    public function getPref() {
        return 'tokyo';
    }
}

/* birdクラスの定義 */
class bird {
    public function getBird() {
        return 'yurikamome';
    }
}

call.php にはcall という名前空間を定義します。
インポートとエイリアスを作成します。

call.php
<?php

namespace call;

require_once 'tokyo.php';

/* 名前空間のインポート */
use asia\japan\kanto;

/* birdクラスのエイリアスを作成 */
use asia\japan\kanto\tokyo\bird as tori;

call2.phpにはcall.phpと同じ名前空間を定義します。
call.phpでインポート、作成したエイリアスを call2.php で利用してみます。

call2.php
<?php

namespace call;

require_once 'tokyo.php';
require_once 'call.php';

/* インポートを利用 */
$a = new kanto\tokyo\pref;
echo $a->getPref();

/* エイリアスを利用 */
$b = new tori;
echo $b->getBird();

実行すると、エラーが表示されました。

エラー
Fatal error: Class 'call\kanto\tokyo\pref' not found in C:\xampp\htdocs\call2.php on line 9

先ほどと同様に pref クラスが見つからないと書いてあります。
インポートが機能していません。
こちらも先ほどと同様に、エイリアスを利用した場合を確かめましたが、クラスが見つからないとのエラーが表示されました。
別ファイルの同じ名前空間からインポート・エイリアスを利用できませんでした。

次のパターンも確認しましょう。

別ファイルの別の名前空間からインポート・エイリアスを利用

tokyo.php の記述は先ほどと同様です。

tokyo.php
<?php
namespace asia\japan\kanto\tokyo;

/* prefクラスの定義 */
class pref {
    public function getPref() {
        return 'tokyo';
    }
}

/* birdクラスの定義 */
class bird {
    public function getBird() {
        return 'yurikamome';
    }
}

call.php も先ほどと同様の記述です。

call.php
<?php

namespace call;

require_once 'tokyo.php';

/* 名前空間のインポート */
use asia\japan\kanto;

/* birdクラスのエイリアスを作成 */
use asia\japan\kanto\tokyo\bird as tori;

call2.php には call.php とは別の名前空間を定義します。
call.phpでインポート、作成したエイリアスを call2.php で利用してみます。

call2.php
<?php

namespace call2;

require_once 'tokyo.php';
require_once 'call.php';

/* インポートを利用 */
$a = new kanto\tokyo\pref;
echo $a->getPref();

/* エイリアスを利用 */
$b = new tori;
echo $b->getBird();

実行すると、エラーが表示されました。

エラー
Fatal error: Class 'call2\kanto\tokyo\pref' not found in C:\xampp\htdocs\call2.php on line 9

先ほどと同様に pref クラスが見つからないと書いてあります。
インポートが機能していません。
こちらも先ほどと同様に、エイリアスを利用した場合を確かめましたが、クラスが見つからないとのエラーが表示されました。
別ファイルの別の名前空間からインポート・エイリアスを利用を利用できませんでした。

検証結果としては、インポート・エイリアスの有効範囲は、同ファイルの同じ名前空間のみでした。

  同じ名前空間 別の名前空間
同じファイル ×
別のファイル × ×

考えてみれば、別ファイルや他の名前空間のインポート・エイリアスが有効だった場合、どこでインポートされたのか、どこでエイリアスが作成されたのか、判別するのに苦労します。
同ファイルの同じ名前空間のみというのは、納得の有効範囲ですね。

定数を使うことで、現在の名前空間名を表示することができます。
最後にその方法を確認しましょう。

現在の名前空間名を表示する

__NAMESPACE__ 定数を記述すると現在の名前空間名を表示してくれます。
確かめてみましょう。

call.php
<?php
namespace call;

echo __NAMESPACE__;

実行すると call と現在の名前空間が表示されました。

これで名前空間について一通り理解できたかと思います。

最後に

今回の記事で超初心者の理解が少しでも深まれば幸いです。
最後まで読んでいただき、ありがとうございました。

PHP関連の記事をまとめていますので、気になるものがあればご覧ください。
超入門というのは徹底入門ではなく、初学者向けに一つ一つ冗長に説明している超入門記事という意味です。

note

note でも記事を公開してるので、興味がある方はご覧ください。

【初学者向けコードリーディング】 PHP の TODO アプリのコードを一緒に読み解こう

7968
学んだことを投稿していきます。誤りがあればご指摘ください。 note でも記事を投稿しています。
https://note.com/7968
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした