PHP名前空間

最近、私のプロジェクトを名前空間にカプセル化し、通常のドキュメントがないという問題に遭遇しました。 私たちが見つけることができたすべてのものは、2009年頃に遡り、ほぼ2012年は庭にあります...見つかった資料には、現在のphpバージョンでは利用できないものを使用する多くの動作不能な場所があります。 この点で、この問題を少し強調したいと思います。

それでは、名前空間または名前空間とは正確には何ですか? 素晴らしいウィキペディアでは、次のように定義しています。

ネームスペース(英語のネームスペース)-特定のセット。モデル、抽象リポジトリ、または一意の識別子(つまり名前)の論理グループ用に作成された環境として理解されます。 名前空間で定義された識別子は、このスペースに関連付けられています。 同じ識別子を複数のスペースで個別に定義できます。 したがって、1つのネームスペースで定義された識別子に関連付けられた値は、別のスペースで定義された同じ識別子と同じ(または、異なる)値を持つ場合と、持たない場合があります。 名前空間をサポートする言語は、識別子がどの名前空間に属するか(つまり、その定義)を示す規則を定義します。 ウィキ




すべてが明確ですか? 実際、すべてがシンプルです。 バージョン5.3より前のphpには、グローバル(メインコードが実行された)とローカル(関数変数が定義された)の2つのスペースしかありませんでした。

画像

バージョン5.3以降、すべてが変更されました。 これで、クラスメソッドが存在するネームスペースなどを定義できます。

画像

私はそれが少し明確になったことを望みます。



私は特にクラスを同じと呼びました。 これらは異なるスペースで定義されているため、これらは同じ名前にもかかわらず2つの異なるクラスです。 メインスクリプトは、以前と同様、グローバルスペースで機能しますが、ここでは何も変更されておらず、クラスと機能を定義できます。 では、なぜスペースが必要なのでしょうか? まず、ファイルを何らかのフレームワークまたはライブラリに接続するときに、クラスがフレームワーククラスをオーバーライドしたり、その逆を行ったりしないようにします。



名前空間で定義されたクラスを使用するには、定義したスペースを適切な場所にあるグローバルスペースにインポートする必要があります(通常、ファイルの先頭でこれを行うことを好みます)
use
      
      





警告:何らかの理由で、phpは条件ブロックとループでuseキーワードを使用できません




写真から例を取り上げて、コードに実装してみましょう。

注: namespaseキーワードは、<?の直後のファイルの先頭に配置する必要があります。 php


A.phpファイル

 <? php namespace A { class A { public static function say() { echo '   '; } } }
      
      





B.phpファイル

 <? php namespace B { class A { public static function say() { echo '   B'; } } }
      
      





代替構文が可能です:

 <? php namespace A; class A { public static function say() { echo '   '; } }
      
      







各ネームスペースを個別のファイルで宣言することをお勧めします。 それは1つで可能ですが、厳密にはお勧めできません!

次に、メインスクリプトが機能する3番目のファイルに移動します。

index.php

 <? php require_once 'A.php'; require_once 'B.php'; use A\A; use B\A;
      
      





コードだけが追加されたという利点があるように見えますが、これは完全に真実ではありません。もう少し、スタートアップクラスの例を示します。

では、クラスを見てみましょう

 <? php require_once 'A.php'; require_once 'B.php'; use A\A; use B\A; A\A::say(); B\A::say();
      
      





注: php名前空間でスコープ解決演算子(::)を使用することできません ! 適切な唯一の理由は、静的クラスのメソッドと定数を参照することです。 最初は、ネームスペースに使用したかったのですが、問題が発生したため拒否しました。 したがって、A :: A :: say();という形式の構築 無効であり、エラーになります。


名前空間の場合、バックスラッシュ文字「\」を使用する必要があります

注意:誤解を避けるために、行で使用される場合、この文字をエスケープする必要があります: '\\'




名前空間は互いにネストできます。A.phpファイルを追加しましょう。

 <? php namespace A { class A { public static function say() { echo '   '; } } } namespace A\subA { class A { public static function say() { echo '   '; } } }
      
      





インデックスには次のように書きます:

 <? php require_once 'A.php'; require_once 'B.php'; use A\A as A; use B\A as B; use A\subA as sub A::say(); A::say(); sub::say();
      
      







重要なポイントは、インポートされたスペースにエイリアスを使用することです。 A \ subA :: say();と書くことができます。 同意します。これを回避するために毎回スペースへのフルパスを書くことは困難です。エイリアスが導入されました。 コンパイル時に、エイリアスsubがA \ subAに置き換えられる代わりに、次のようになります。そのため、呼び出しA \ subA :: say();



しかし、グローバル空間で定義された関数が呼び出されるとどうなりますか? PHPはまず、現在作業しているスペース内で関数を探し、見つからない場合はグローバルスコープを参照します。 グローバル関数を使用していることをすぐに示すには、その前にバックスラッシュを置く必要があります。



スペースからのクラスの自動ロードに関する問題を回避するには、スペースの編成と同様にファイルシステムを編成する必要があります。 たとえば、クラスが保存されるクラスのルートフォルダーがあり、スペースは次のように整理できます。

クラス\ A \ A.php

classes \ A \ sub \ A.php(サブスペースを別のファイルに取り出します)

クラス\ B \ B.php



PHPには、現在のスペースの名前を含むマジック定数__NAMESPACE__があります。



そして今、スタートアップについて。



以下のクラスは私のものではなく、私はそれを動作させ、 どこからでも取り入れられたわずかに改善しました。

注:クラスをロードするには、クラス名がファイル名と一致する必要があります!




 <?php namespace yourNameSpace { class Autoloader { const debug = 1; public function __construct(){} public static function autoload($file) { $file = str_replace('\\', '/', $file); $path = $_SERVER['DOCUMENT_ROOT'] . '/classes'; $filepath = $_SERVER['DOCUMENT_ROOT'] . '/classes/' . $file . '.php'; if (file_exists($filepath)) { if(Autoloader::debug) Autoloader::StPutFile((' ' .$filepath)); require_once($filepath); } else { $flag = true; if(Autoloader::debug) Autoloader::StPutFile(('  ')); Autoloader::recursive_autoload($file, $path, &$flag); } } public static function recursive_autoload($file, $path, $flag) { if (FALSE !== ($handle = opendir($path)) && $flag) { while (FAlSE !== ($dir = readdir($handle)) && $flag) { if (strpos($dir, '.') === FALSE) { $path2 = $path .'/' . $dir; $filepath = $path2 . '/' . $file . '.php'; if(Autoloader::debug) Autoloader::StPutFile(('  <b>' .$file .'</b> in ' .$filepath)); if (file_exists($filepath)) { if(Autoloader::debug) Autoloader::StPutFile((' ' .$filepath )); $flag = FALSE; require_once($filepath); break; } Autoloader::recursive_autoload($file, $path2, &$flag); } } closedir($handle); } } private static function StPutFile($data) { $dir = $_SERVER['DOCUMENT_ROOT'] .'/Log/Log.html'; $file = fopen($dir, 'a'); flock($file, LOCK_EX); fwrite($file, ('║' .$data .'=>' .date('dmY H:i:s') .'<br/>║<br/>' .PHP_EOL)); flock($file, LOCK_UN); fclose ($file); } } \spl_autoload_register('yourNameSpace\Autoloader::autoload'); }
      
      





ロードするクラスの名前を見ると、各クラスの前に、使用中に指定されている名前空間のプレフィックスが付いていることがわかります。 そのため、名前空間に類似したディレクトリ内のファイルの場所を使用することをお勧めします。これにより、検索が1〜2回繰り返されます。



これで、インデックスは次のように記述できます。

 <? php require_once 'Autoloader.php'; use Autoloader as Autoloader; use A\A as A; use B\A as B; use A\subA as sub A::say(); A::say(); sub::say();
      
      





これで、使用するすべてのクラスとインターフェースが自動的にロードされます。



スペースを持つ言語の動的機能の一部を示すために、別のクラスを宣言します。

test.php

 <? php namespace mySpace { class test { __construct() { //; } function sayName($name) { echo ' ' . $name; } static function sayOther() { echo ' '; } } }
      
      







index.php

 <? php require_once 'Autoloader.php'; use Autoloader as Autoloader; use mySpace\test as test //,    $class = 'test'; //    $obj = new $class; $obj->sayName('test'); //   test\sayName('test2'); //  $obj::sayName('test'); //   test::sayName('test2');
      
      







私の記事が誰かに役立つことを願っています。



All Articles