PHP対象プログラム設計(oop)学習ノート(五)-PHP名前空間

5717 ワード

名前空間の概要
PHPにおいて、名前空間はクラスライブラリまたはアプリケーションの作成時に重用可能なコード、クラスまたは関数の作成時に発生する2つの問題を解決するために使用されます。
ユーザーが作成したコードはPHP内部のクラス/関数/定数または第三者クラス/関数/定数との間の名前と競合します。長い識別子名(通常は第1のクラスの問題を緩和するために定義される)のために別名(または短い)の名前を作成し、ソースコードの読み取り可能性を向上させる。PHP名前空間は関連するクラス、関数、定数を組み合わせるルートを提供しています。PHP名前空間文法の例を説明します。
名前空間を定義
任意の合法的なPHPコードは名前空間に含まれますが、三つのタイプのコードだけが名前空間に影響されます。クラス、関数、定数です。名前空間はキーワードnamespaceによって宣言されます。ファイルに名前空間が含まれている場合、他のすべてのコードの前に名前空間を宣言しなければなりません。また、PHPの他の言語の特徴とは異なり、同一の名前空間は複数のファイルに定義されてもよく、つまり同じ名前空間の内容を異なるファイルに分割して保存することができる。もちろん、同じファイルで複数の名前空間を定義することもできます。

namespace MyProject;
class MyClass
{
    #code...
}
サブ名前空間を定義します。ディレクトリとファイルの関係が似ています。PHP名前空間も階層化された名前空間の名前を指定できます。したがって、名前空間の名前は階層的に定義されます。

namespace MyProject\helper\http;
class MyClass
{
    #code...
}
同じファイルの中で複数の名前空間を定義します。同じファイルの中で複数の名前空間を宣言するには二つの方法がありますが、実際のプログラミングの実践では、同じファイルの中で複数の名前空間を定義することはあまり提唱されていません。この方式は主に複数のPHPスクリプトを同一ファイルに統合するために用いられる。最初の方法を以下に示します。

namespace MyProject\helper\http;
class MyClass
{
    #code...
}
namespace MyProject\helper\request;
class MyClass
{
    #code...
}
ただし、この方法は強く推奨されていません。以下の大括弧定義法を参照してください。

namespace MyProject\helper\http;
{
    class MyClass
    {
        #code...
    }
}
namespace MyProject\helper\request;
{
    class MyClass
    {
        #code...
    }
}
PHP名前空間の元素使用
名前空間の使い方を議論する前に、PHPはどの名前空間の要素を使うかを知る必要があります。クラス名は3つの方法で参照できます。
名前を限定しない、またはプレフィックスのクラス名を含まない、例えば$a=new foo()またはfoo:staticmethod();現在の名前空間がcurrentnamespaceであれば、fooはcurrentnamespace\fooとして解析されます。fooを使用するコードがグローバルで、名前空間に含まれていないコードであれば、fooはfooとして解析されます。警告:名前空間の関数または定数が定義されていない場合、その非限定の関数名または定数名は大域関数名または定数名として解析されます。詳細は名前空間を参照してください。グローバル関数名/定数名を用意します。
名前を限定するか、またはプレフィックスの名前を含みます。例えば$a=new subnamespace\foo()またはsubnamespace\foo:staticmethod();現在の名前空間がcurrentnamespaceであれば、fooはcurrentnamespace\subnamespace\fooとして解析されます。fooを使用するコードがグローバルで、名前空間に含まれていないコードであれば、fooはsubnamespace\fooとして解析されます。
名前を完全に定義し、またはグローバルプレフィックス演算子の名前を含み、例えば$a=new\currentnamespace\foo()または\currentnamespace\foo::staticmethod();この場合、fooは常にコード内の文字名currentnamespace\fooとして解析される。名前空間を使う:エイリアス/インポート
別名参照または外部からの完全限定名称の導入を許可することは、名前空間の重要な特徴である。PHP名前空間サポートには別名または導入方式があります。クラス名に別名を使用したり、名前空間名に別名を使用したりします。PHPでは、別名はオペレータUSeにより実現されます。
注意PHPは導入関数や定数に対応していません。

namespace foo;
use My\Full\Classname as Another;

// use My\Full\NSname as NSname
use My\Full\NSname;

//
use \ArrayObject;

名前解析規則
名前解析規則を説明する前に、重要な定義を見ます。
名前には名前空間区切り子の識別子が含まれていません。例えば、Foo限定の名前Qualfied name:名前には名前空間区切り子の識別子が含まれています。例えば、Foo\Barは完全に名前Fullyqualifed nameを定義します。名前には名前空間区切り子が含まれています。名前空間区切り記号で始まる識別子は、例えばFoo\Barです。namespace\Fooも完全限定名称です。名称解析は以下の規則に従う。
名前を完全に定義した関数、クラスと定数の呼び出しはコンパイル時に解析されます。例えばnew\A\BはクラスA\Bに解析されます。すべての非限定名称と限定名称(完全限定名ではない)は、現在の導入規則に従ってコンパイル時に変換されます。例えば、名前空間A\B\CがCに導入されると、C\D\e()への呼び出しはA\B\C\D\e()に変換されます。名前空間内では、導入規則に従って変換されていないすべての名前に、現在の名前空間名が付けられます。例えば、名前空間A\Bの内部でC\D\e()を呼び出すと、C\D\e()はA\B\C\D\e()に変換されます。非限定クラス名は、現在の導入規則に従ってコンパイル時に変換されます。例えば、名前空間A\B\CがCに導入されると、new C()はnew A\B\C()に変換される。名前空間の内部(例えばA\B)では、名前を限定しない関数に対して呼び出しを実行時に解析します。例えば、関数foo()への呼び出しは、現在の名前空間において、A\B\foo()という関数2を探してグローバル空間の関数foo()を探して呼び出します。名前空間(例えばA\B)内で、名前や名前類(完全に限定されていない名前)を限定する呼び出しは、運転時に解析されます。new C()およびnew D\E()を呼び出した解析手順:new C()の解析:現在の名前空間でA\B\Cクラスを検索します。クラスA\B\Cを自動搭載してみます。
new D\E()の解析:クラス名の前に現在の名前空間名を付けて、A\B\D\Eとなり、クラスを探します。クラスA\B\D\Eを自動搭載してみます。
グローバル名前空間のグローバルクラスを引用するためには、完全に定義された名称new\C()を使用する必要があります。
Example名前解析例

<?php
namespace A;
use B\D, C\E as F;
//
foo();      // "A" foo()
            // "foo"
\foo();     // "foo"
my\foo();   // "A\my" "foo"
F();        // "A" "F"
            // "F"
//
new B();    // "A" "B"
            // , "A\B"
new D();    // , "B" "D"
            // , "B\D"
new F();    // , "C" "E"
            // , "C\E"
new \B();   // "B"
            // , "B"
new \D();   // "D"
            // , "D"
new \F();   // "F"
            // , "F"
//
B\foo();    // "A\B" "foo"
B::foo();   // "A" "B" "foo"
            // "A\B" , "A\B"
D::foo();   // , "B" "D" "foo"
            // "B\D" , "B\D"
\B\foo();   // "B" "foo"
\B::foo();  // "B" "foo"
            // "B" , "B"
//
A\B::foo();   // "A\A" "B" "foo"
              // "A\A\B" , "A\A\B"
\A\B::foo();  // "A\B" "B" "foo"
              // "A\B" , "A\B"
?>