PHPの公式ドキュメントの名前空間(Namespace)についてまとめてみた 名前空間の宣言 その1

# 名前空間

PHPを勉強しているので, それをまとめてみた.

PHPの公式マニュアルを読んで, それをまとめています.

自分なりの解釈がめっちゃ入っているので, 間違えていればコメントで教えてください, お願いします.

## 参考文献

公式ドキュメント[namaespace](http://php.net/manual/en/language.namespaces.php)

## 環境

PHPの環境(`php -v`の出力)

```
PHP 7.2.5-0ubuntu0.18.04.1 (cli) (built: May  9 2018 17:21:02) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
with Zend OPcache v7.2.5-0ubuntu0.18.04.1, Copyright (c) 1999-2018, by Zend Technologies
```

windows 10 proで, Ubuntu18.04を動かして, そこで動作確認しています.

## 名前空間とは

名前空間(namespace)について, ざっくり説明してみましょう.

PHPに限らず, 一般的な説明をするなら, 

```
名前空間とは, ものをカプセル化することです.
```

(ここでは, オブジェクト指向のカプセル化とは別の意味でつかわれています)

はっきり言って意味が分かりません.

もっと具体的に話をしてみましょう.

例えば, `田中 花子`という人がいたとしましょう.

その子は, 田中家ではもちろん`田中 花子`は, 花子と呼ばれていると思います(は?そんなことない, 親から苗字, or フルネームで呼ばれてるわ！って人がいたら教えてください).

しかし, 学校に行くと, もう一人`佐藤 花子`がいるとしましょう.

そうすると, 学校では, 花子と呼ぶとどちらの花子なのかわかりません.

そうすると, もう花子と学校で呼ぶことはできません.

そこで, 苗字と合わせて呼ぶことで, どちらの花子を呼んでいるか判別できます.

家族の中にいるときは, `田中 花子`は, `花子`と呼ばれても識別されます.

一度外(学校)に行くと, `花子`では, 識別できません.

しかし, 苗字を付けることで, 識別されます.

なので, 家族が違えば, 同じ名前を付けても問題は起こらない.

これがカプセル化です.

苗字(家族)というカプセルを作って, その中でなら, `田中 花子`は花子と呼ぶことができる.

違うカプセル(ここでは, 佐藤)の中ならば, 違う個体(言い方悪い)でも, 同じ名前を使うことができます.

そして, カプセルの外では, 苗字をつけて, カプセル内では, 同じ名前だけれど, 別々の個体を, 識別することができます(`田中 花子`と`佐藤 花子`)

ほかにも, ファイルシステムでも, 名前空間は使われています.

例えば, 同じフォルダ(ディレクトリ)には, 同じ名前のファイルは作れません.

これは, 上の例でいう 学校では, `田中 花子`と`佐藤 花子`を花子と呼ぼうとしている状態です.

違うフォルダならば, 同名のファイルを作ることができます.

これは, `佐藤`という家族(ファイルシステムでは, フォルダ. 抽象的には, カプセル)と`田中`という家族では, 花子と呼べるということと同じです.

なんとなく雰囲気がつかめたところで, PHPの名前空間(Namespace)について, 話をしましょう.

(一般の名前空間の話はここで, 終わり)

そもそも, なぜPHPには, 名前空間が必要か?

phpの公式ドキュメントでは, 二つの問題を解決するためと書かれています.

> 1. Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
2. Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.

1の言っていることは, 自分の作ったコードと, PHPの内部のコード(PHPをインストールしたら勝手についてくる便利なコード)のクラスや関数, また, 外部ライブラリのクラスや関数やらの名前がぶつかってしまい, どっちが呼び出されるのか分からなくなる現象(Name collisions, 日本語は知らない)が起きてしまうのを防ぐ.

2は, 1の問題を和らげるために, 別名をつけるための仕組みとして機能している.

さて, 実際にコードを試しながら, PHPの名前空間をどう使っているのか見ていきます.

## PHPの名前空間宣言のsyntax
versionは, php 5.3以上 or php7で動作するらしいです(accroding to 公式ドキュメント).

PHPで, 名前空間を宣言するには, `namespace`キーワードを使います.

いきなりですが, コードを見てみましょう.

```php:namespace.php
<?php
namespace MyProject;

const CONNECT_OK   = 1;
const CONNECT_FAIL = 0;

class Connection()
{
/* .... */
}

function connect()
{
/* ..... */
}
```

一行目の`namespace`というキーワードの後に, 名前空間の名前を裸のまま(`"`とか`'`とかつけないで)宣言します.

この上の例では, `MyProject`というカプセルができたことになります.

他のコードで, `Connection`や`connect`などの名前を使っても大丈夫なことになります.

ここで, いくつか注意点があります.

namespaceの宣言は, コードの一番最初にしなければいけません.

`namespace MyProject`の前の行に, `<?php`以外の文字があると以下のようなerrorになります.

```
PHP Fatal error:  Namespace declaration statement has to be the very first statement or after any declare call in the script
```

公式ドキュメントには,

>The only code construct allowed before a namespace declaration is the declare statement, for defining encoding of a source file.
In addition, no non-PHP code may precede a namespace declaration, including extra whitespace:

とあるので, `<?php`の上に何か文字を入れてもエラーになります(ならない環境があるのか不明).

つまり, htmlファイルの中に埋め込まれているphpは, `namespace`の宣言は使えないことになります.

実は例外が一つだけあり, `declare`だけは, `namespace`の前においてもエラーになりません.

これは, `declare`が, コンパイラ中に処理されるからだと思われます.

次は, [サブ名前空間について](https://qiita.com/drafts/a3c5fa665b2983c0410a)です.