◆ やっぱり PHP クオリティです

PHP にはいつのころからか 名前空間機能ができました
でも もともとはないものだったのでなくてもそこまで困りません

大きなものを作るときなら あったほうがいいかもしれません
インナークラスも作れないので名前衝突可能性が高くなりますし

ただ私の場合はちょっとしたスクリプトで node.js より PHP のほうが楽そうなときに使うことばかりで いわば shell script 代わりです
なのでこれまで名前空間はほぼ使ったことはありませんでした

C# だと .NET Framework の組み込みのライブラリが名前空間で管理されてるので意識する必要があります
C# の影響もあってなんとなく PHP で名前空間使ってみようとしたら C# とは違う微妙な仕様でした

C# の場合

まずは C# の場合です

namaespace という名前空間にクラスと enum を定義します

[a.cs]
namespace namaespace
{
    public class C1 { }
    public class C2 { }
    public enum E { e }
}

別の名前空間 app のプログラムからこれらを参照します

[b.cs]
namespace app
{
    public class Program
    {
        public static void main()
        {
            new namaespace.C1();
            new namaespace.C2();
            var e = namaespace.E.e;
        }
    }
}

名前空間もつけてクラス名や enum 名をかけば参照できます

毎回書くのは面倒なので using を使うとこう書けます

[c.cs]
using namaespace;

namespace app
{
    public class Program2
    {
        public static void main()
        {
            new C1();
            new C2();
            var e = E.e;
        }
    }
}

using で namaespace を指定しているので namaespace にあるものは直接書くことができます

PHP の場合


[a.php]
<?php

namespace a;
use \b;

require "b1.php";
require "b2.php";

$b1 = new B1();
$b2 = new B2();

[b1.php]
<?php

namespace b;

class B1 { }

[b2.php]
<?php

namespace b;

class B2 { }

b と言う名前空間に B1 と B2 クラスがあります
a と言う名前空間で use \b を指定しています

PHP では \ が名前空間の区切り文字でパスの / みたいなものです
\b はルートの b を表すことになります

a.php を実行すると一見何も問題なさそうですが
Fatal error: Uncaught Error: Class 'a\B1' not found in C:\code\phpns\a.php on line 9

Error: Class 'a\B1' not found in C:\code\phpns\a.php on line 9

Call Stack:
    0.0003     353976   1. {main}() C:\code\phpns\a.php:0

PHP Fatal error:  Uncaught Error: Class 'a\B1' not found in C:\code\phpns\a.php:9
Stack trace:
#0 {main}
  thrown in C:\code\phpns\a.php on line 9

終了コード: 255

a\B1 はありませんと言うエラーになります
b\B1 ではなく 名前空間 a を見ています


クラスを参照するところをちょっと変えてみます

[a.php]
<?php

namespace a;
use \b;

require "b1.php";
require "b2.php";

$b1 = new b\B1();
$b2 = new b\B2();

これだとエラーなしです

これから 「use \b」 をなくすと
Uncaught Error: Class 'a\b\B1' not found

a 名前空間の中から b\B1 を探そうとしています
use \b があると b 空間から探しているのでエラーなくみつけることができています


ということからわかるように PHP の use は指定した名前空間の中のクラスなどを直接読み込めるようにしてくれるものではありません
単純にエイリアスというだけです

シンプルな 1 階層なので
new \b\B1();
use \b;
new b\B1();
でほぼ違いがなかったのですが 名前空間が深くなると必要性がでてきます

[b.php]
<?php

namespace b\c\d\e\f\g\h\i\j\k;

class B1 { }

[a.php]
<?php

namespace a;
use \b\c\d\e\f\g\h\i\j\k;

require "b1.php";

$b1 = new k\B1();

k\B1 だけで済みます


でも やっぱり 「k」 邪魔です
なんで C# みたいなものにしなかったんだろう
use してるんだからその名前空間ものはプレフィックスなしに書けるようにしてほしいです

関数も use があるかどうかで 標準に存在する関数か自作を切り替えれるようになってほしいです
例えば array_map(~); と書いていても use ~; って入れるだけで PHP の関数からその名前空間にある関数になって動きを変えれるとか

use いっぱいすると名前被る可能性もありますが それなら被る場合にだけ プレフィックス付きにすればいいと思います


PHP は PHP だなぁ と思える仕様でした