📝

【PHP】namespace(名前空間)、use の解説

2023/06/13に公開

はじめに

PHPの「namespace(名前空間)」と「use」について解説します。

学習するPHP機能

namespace

namespace
// 例: namespace {名前空間};
namespace App\Models;

// \App\Models\Admin クラス
class Admin {}

use

use例1
// 例: use {完全修飾名(先頭「\」は除く)} as {別名};
use App\Models\Admin as AdminModel; // 別名: AdminModel
use例2
// 例: use {完全修飾名(先頭「\」は除く)};
use App\Models\Admin; // 別名: Admin

学習の事前準備

以下について理解している前提で進みます。

PHPの名前空間とは

名前空間(namespace)とは、コード内で重複するクラス・関数を区別するための機能です。
まずは、名前空間を使わない場合について見ていきます。

例えばフレームワークなどで、既にStrというクラスが定義されている場合、
別途、自分でStrクラスを定義しようとすると、クラス名が重複するためエラーが発生します。

コード例
Utils.php(フレームワーク)
class Str{} // \Str クラス
class Arr{} // \Arr クラス
MyUtils.php(自前)
class Str{} // \Str クラス
// PHP Fatal error:  Cannot declare class Str, because the name is already in use
//                 (名前がすでに使用されているため、クラスStrを宣言することができません。)

これを解決するのが名前空間(namespace)です。
ファイルシステムで例えると、クラスがファイル、名前空間がフォルダの役割になります。

コード例
Utils.php(フレームワーク)
namespace Illuminate\Support;
class Str{} // \Illuminate\Support\Str クラス
class Arr{} // \Illuminate\Support\Arr クラス
MyUtils.php(自前)
namespace My;
class Str{} // \My\Str クラス
// 完全修飾名(名前空間+クラス名)が重複しないためエラーにならない

完全修飾名

完全修飾名(かんぜんしゅうしょくめい)は、絶対パスのイメージで\から始まり、名前空間とクラス名を\区切りで連結した名称です。
名前空間を含めた完全名称(フルパス)を指すもので、同名のクラス名があった場合でも、完全修飾名が異なれば利用が可能になります。

例えば以下の6つのクラスは共存が可能です。

名前空間
(namespace)
クラス名
(class)
完全修飾名
\{名前空間}\{クラス名}
Illuminate\Support Str \Illuminate\Support\Str
Illuminate\Support Arr \Illuminate\Support\Arr
App Str \App\Str
App Arr \App\Arr
なし Str \Str
なし Arr \Arr
イメージ
コード
<?php
namespace Illuminate\Support;
class Str {}
class Arr {}
<?php
namespace App;
class Str {}
class Arr {}
<?php
class Str {}
class Arr {}

use

useはクラスや関数にエイリアス(別名)をつける機能です。

useを使う例、使わない例で見ていきましょう。
まずは、以下のStrクラスをStringUtilsクラスで使用してみましょう。

  • 名前空間: Illuminate\Support
  • クラス名: Str
  • 完全修飾名: \Illuminate\Support\Str
  • StringUtilsクラスで使用するメソッド: upper
コード
Str.php
<?php

namespace Illuminate\Support;

class Str
{
    public static function upper(string $value): string
    {
        return mb_strtoupper($value, 'UTF-8');
    }
}
StringUtils.php
<?php

namespace App\Utils;

class StringUtils
{
    public static function upperCase(string $value): string
    {
        // TODO: \Illuminate\Support\Strクラスのupperメソッドの結果を返す。
    }
}

useを使わない例

以下のように完全修飾名でクラスを使用します。

\Illuminate\Support\Str
StringUtilsクラスでの使用例
StringUtils.php
 <?php
 
 namespace App\Utils;
 
 class StringUtils
 {
     public static function upperCase(string $value): string
     {
-        // TODO: \Illuminate\Support\Strクラスのupperメソッドの結果を返す。
+        return \Illuminate\Support\Str::upper($value);
     }
 }

useを使う例1

以下のようにuseでエイリアス(別名)を作成し、クラスを使用します。
ここではIlluminateSupportStrという名前で、クラス参照ができるようにします。
useas間には、完全修飾名を入れますが先頭の「\」は除きましょう。

use Illuminate\Support\Str as IlluminateSupportStr;
IlluminateSupportStr
StringUtilsクラスでの使用例
StringUtils.php
 <?php
 
 namespace App\Utils;
 
+use Illuminate\Support\Str as IlluminateSupportStr;
+
 class StringUtils
 {
     public static function upperCase(string $value): string
     {
-        return \Illuminate\Support\Str::upper($value);
+        return IlluminateSupportStr::upper($value);
     }
 }

useを使う例2

as {別名} を省略すると、完全修飾名の末端の名称(クラス名)が別名として扱われます。
これが一般的な使い方になり、PHPマニュアルでは「インポート」と呼びます。

use Illuminate\Support\Str; // 『use Illuminate\Support\Str as Str』 と同じ
Str
StringUtilsクラスでの使用例
StringUtils.php
 <?php
 
 namespace App\Utils;
 
-use Illuminate\Support\Str as IlluminateSupportStr;
+use Illuminate\Support\Str;

 class StringUtils
 {
     public static function upperCase(string $value): string
     {
-        return IlluminateSupportStr::upper($value);
+        return Str::upper($value);
     }
 }

標準クラスを使用する

名前空間を設定した場合に注意が必要なのが
Exception」、「DateTime」等のPHP標準クラスを使用する場合です。

例えば namespace App を設定したコードで「Exception」クラスを使用する際に
そのままの名称で使用すると「Class "App\Exception" not found」とエラーになります。
使用側のクラスが名前空間に属していた場合、そこからの相対パスとなってしまうため
存在しない\App\Exceptionクラスを参照していることになります。

PHP標準クラスは名前空間なしで直接定義されているため、useするか、完全修飾名で参照する必要があります。

// 完全修飾名
$e = new \Exception();
// use を使用
use Exception;
$e = new Exception();
サンプルコード

エラーケース

A.php
<?php
namespace App;

class A
{
    public static function run()
    {
        $e = new Exception(); // PHP Fatal error:  Uncaught Error: Class "App\Exception" not found
    }
}

A::run();
echo '正常終了';

完全修飾名のケース

A.php
 <?php
 namespace App;
 
 class A
 {
     public static function run()
     {
-        $e = new Exception();
+        $e = new \Exception();
     }
 }
 
 A::run();
 echo '正常終了';

use のケース

A.php
 <?php
 namespace App;
 
+use Exception;
+
 class A
 {
     public static function run()
     {
         $e = new Exception();
     }
 }
 
 A::run();
 echo '正常終了';

課題

課題1

課題
Carbon.php
<?php
namespace Carbon;

class Carbon
{
}
HomeController.php
<?php
namespace App\Http\Controllers;

use XXXX; // ← ここにに入れる名称を答えなさい。

class HomeController
{
    public function run()
    {
        $now = new Carbon(); // 定義したクラスを使用
    }
}
解答

定義したクラスが、名前空間「Carbon」、クラス名「Carbon」のため
完全修飾名が「\Carbon\Carbon」になり
useを使用する場合、先頭の「\」を除くため
Carbon\Carbon」が解答となる。

HomeController.php
 <?php
 namespace App\Http\Controllers;
 
-use XXXX; // ← ここにに入れる名称を答えなさい。
+use Carbon\Carbon;
 
 class HomeController
 {
     public function run()
     {
        $now = new Carbon(); // 定義したクラスを使用
     }
 }

課題2

課題
解答

課題3

課題
解答

使用側のクラスであるDatabaseSeederクラスには、名前空間 Database\Seeders が設定されており
クラス使用時はAdminSeederと記述しており、相対参照のため完全修飾名は\Database\Seeders\AdminSeederとなる

最後に

今回、解説したのは最低限の部分のみで、
特にuseに関しては、関数や定数のエイリアス/インポートを行うこともできます。
詳細についてはPHPマニュアルなどを参照してください。

参考

https://www.php.net/manual/ja/language.namespaces.php

関連書籍

https://amzn.to/3O7Td5A
https://amzn.to/3WXfMhn

Discussion