PHPのnamespaceについて


#namespace（名前空間）とは

namespaceはFinderやエクスプローラーなどのパスに似ています。
例えば、Finderやエクスプローラーでは同じフォルダー内に同じ名前のファイルを作ることはできません。しかしフォルダーが違えば同じファイル名のものを複数作ることが可能になります。

これと同じように、namespaceにクラスやメソッドなどを記述することでnamespaceが異なるものであれば、同じ名前のクラスやメソッドが使えるようになります。

#namespaceを使ってみる

```php:qiita.php
<?php

namespace morning;

function greeting(){
   echo "おはようございます";
}

namespace evening;

function greeting(){
   echo "こんばんは";
}
```
ここでは`morning`と`evening`という名前空間に、`greeting()`という同じ名前のメソッドを格納しました。
この`greeting()`を別のファイルで呼び出してみます。
`namescapeで指定した名称 + \(バックスラッシュ) + 呼び出したいもの`
または
`namespace + namescapeで指定した名称; 
呼び出したいもの;`
と記述することで呼び出すことができます。

```php:namespaceで設定した関すを呼び出す
<?php

//namespaceを宣言してあるファイルを読み込む
require 'qiita.php';

//namespadeで指定したメソッドを呼び出す
morning\greeting();
echo "<br>";
evening\greeting();

```
実行結果

```
おはようございます
こんばんは
```
同じメソッド名を指定してもnamespaceが違うためエラーにならず、正常に実行できました！
ちなみにnamespaceの宣言は波括弧{}を使っても記述することができます。（今回は割愛）

#サブ名前空間を使ってnamespaceを指定してみる

サブ名前空間はディレクトリの構造と同じようにnamespaceにパスを指定する形で名前空間を指定する方法になります。
サブ名前空間を使うことでnamespaceの名前が重複してしまうのを防ぐことができます。
`namespace サブ名前空間\サブ名前空間\サブ名前空間`とすることで指定できます。
スラッシュ`/`ではなく、バックスラッシュ`\`で記述します。

```php:yamada.php
<?php

namespace ABCSchool\classA\Yamada;

function greeting(){
   echo "A組の山田です。";
}

```

##サブ名前空間の指定形式
サブ名前空間をどのように呼び出すかは、下記の３パターンがあります。
<font color="red">これらはnamespaceをどの階層までを呼び出しているのかというところが着眼点なのかなと思います。
</font>
`yamada.php`は以下の階層のものであるとして３パターンについて見ていきます。
>
***yamada.phpの階層***
ABCSchool/
　　└ classA/
　　　　└ yamada.php


###1. 非修飾形式
非修飾形式は、namespaceを指定したファイルと同じディレクトリ内から指定する際に使います。メソッドを呼び出すときに、指定したnamespaceの全てのパスを呼び出しているので同じディレクトリ内であるとわかります。

下記の例で言うと
`yamada.php`で指定した`namespace ABCSchool\classA\Yamada;`と
`call.php`で呼び出している`namespace ABCSchool\classA\Yamada;`
のパスが同じなので同じディレクトリ内であるとわかります。

同じディレクトリにあるので、メソッドやクラスを呼び出す際に
`namescapeで指定した名称  \サブ名前空間 メソッド名 `
といったようにパス名を記述する必要がなく、単純にメソッド名だけを呼び出せばOKということになります。
<font color="red">※逆にここでパス名を指定するとエラーになります</font>


```php:yamada.php
<?php

//namespaceの指定
namespace ABCSchool\classA\Yamada;

function greeting()
{
    echo 'A組の山田です。';
}

```

```php:call.php
<?php
//ファイルを読み込むよりも先に名前空間を呼び出す
namespace ABCSchool\classA\Yamada;

//namespaceを指定したファイルを読み込む
require 'yamada.php';

//namespaceで定義したメソッドを呼び出す
greeting();
```
実行結果

```
A組の山田です
```

###2. 修飾形式
修飾形式は、相対パスで名前空間を呼び出す形式です。
つまり自分が現在作業しているファイルを基準としてnamespaceを呼び出すということです。

下記の例で言うと、現在は`ABCSchool`というディレクトリ内の`call.php`ファイルで作業をしている状態です。そのためもう少し下の階層にもぐらないと、namespaceで指定したメソッドは使えないと言うことです。

したがって、名前空間のメソッドを呼び出すときは現在いるディレクトリからの下位階層のパスも指定する必要があります。

```php:yamada.php
<?php

//namespaceの指定
namespace ABCSchool\classA\Yamada;

function greeting()
{
    echo 'A組の山田です。';
}

```

```php:call.php
<?php
//ファイルを読み込むよりも先に名前空間を呼び出す
namespace ABCSchool;

//namespaceを指定したファイルを読み込む
require 'yamada.php';

//namespaceで定義したメソッドを呼び出す
classA\Yamada\greeting();
```
実行結果

```
A組の山田です
```


###3. 完全修飾形式
完全修飾形式は、名前空間のクラスやメソッドなどを呼び出す際にルートパスから記述して呼び出す形式です。
最上位の階層から呼び出すため、名前空間の呼び出しはどのディレクトリから行ってもOKです。
<font color="red">ただし呼び出す際は、頭にバックスラッシュ`\`が必要です。</font>

```php:yamada.php
<?php

//namespaceの指定
namespace ABCSchool\classA\Yamada;

function greeting()
{
    echo 'A組の山田です。';
}

```

```php:call.php
<?php
//ファイルを読み込むよりも先に名前空間を呼び出す
namespace ABCSchool\classA;

//namespaceを指定したファイルを読み込む
require 'yamada.php';

//namespaceで定義したメソッドを呼び出す
//完全修飾形式ではあたまにバックスラッシュが必要
\ABCSchool\classA\Yamada\greeting();
```

実行結果

```
A組の山田です
```

#namespaceの拡張機能use
サブ名前空間を利用するとパス形式で名前空間が指定できることが分かりました。
しかし、毎回毎回`namespace ABCSchool\classA\Yamada;`といった具合に記述していくのは大変面倒に感じます。`use`キーワードとはこのような問題を解決する機能になります。

`use`キーワードを使うことで、名前空間の一部または全部を別の名前(エイリアス)に置き換えて指定することができます。

```php
//書き方
use [名前空間の一部または全部・クラス・関数・定数など] as 置き換えたい名前
```
#useの使い方
`as`以降でエイリアス（置き換えたい名前）を作成し、`use`を使ってインポートします。

```php:qiita.php
<?php

namespace ABCSchool\classA\Yamada;
function greeting()
{
    echo 'A組の山田です。';
}

namespace ABCSchool\classA\Sato;
function greeting()
{
    echo 'A組の佐藤です。';
}

namespace ABCSchool\classA\Kinoshita;
function greeting()
{
    echo 'A組の木下です。';
}

namespace ABCSchool\classA\Watanabe;
function greeting()
{
    echo 'A組の渡辺です。';
}
```

```php:call.php
<?php
//namespaceを指定したファイルを読み込む
require 'qiita.php';

// 名前空間の一部を別名称にする
use ABCSchool\classA as ourClass;

//useで定義した別名称を使ってメソッドを呼び出す
ourClass\Yamada\greeting();
echo "<br>";
ourClass\Sato\greeting();
echo "<br>";
ourClass\Kinoshita\greeting();
echo "<br>";
ourClass\Watanabe\greeting();
```
実行結果

```
A組の山田です。
A組の佐藤です。
A組の木下です。
A組の渡辺です。
```
#まとめ
クラスやメソッド名に重複がないようにしていくと、大規模開発などでは長い名前をつけなければならなくなる。そのため、namespaceを指定することで同じ名前のクラスやメソッドを作成することができる。
useキーワードを使うとサブ名前空間で長い名前のnamespaceを指定したとしても別名称に置くことができる。

#参考
 [PHPマニュアル　名前空間の概要](https://www.php.net/manual/ja/language.namespaces.rationale.php)
[【PHP入門】名前空間(namespace/use)の使い方をわかりやすく解説！](https://www.sejuku.net/blog/23555)
[【PHP超入門】名前空間（namespace・use）について](https://qiita.com/7968/items/1e5c61128fa495358c1f)