phpネーミングスペースと自動ロードの違い

14236 ワード

PHPのネーミングスペース(namespace)はphp 5.3後になります.この概念はC#の中ですでにとっくにあって、phpの中のnamespaceは実はc#の概念と同じです.
なぜphpでnamespaceを使うのですか?
namespaceを使用しない場合、各クラスの1つのプロジェクトにおける名前は固定されている必要があります.phpはnewのときにautoloadを呼び出すにしてもロードされたクラスを呼び出すにしても、クラス名に対応するファイルがあるからです.だからnamespaceがないとき、project 1_のような異なるクラスを区別するために、さまざまな命名規則を考えます.school1_class1_Studentまたはproject 2_school_class_Student.
namespaceを導入するとこの有効な回避が可能になり、1つのnamespaceは1つのファイルパスに相当し、このクラスを検索すると、対応するファイルパスに行ってクラス定義ファイルを検索します.
ネームスペースの概要
ネーミングスペースは筆者の知る限り最も早くC++言語に由来するはずであり、C++98標準以降、様々なネーミングが一致しないことを保証するために提案されたソリューションである.現在のオブジェクト向け言語には基本的にこのようなメカニズムがありますが、もちろんネーミングスペースのほかにもモジュール化など多くの方法がありますが、実際にはこれらのメカニズムはパッケージ問題を解決するために使われているので、個人的には良し悪しの区別はないと思います.まずPHP公式ドキュメントコードを引き出して

namespace my\name; //    "      "   
class MyClass {}
function myfunction() {}
const MYCONST = 1;
$a = new MyClass;
$c = new \my
ame\MyClass; // " " $a = strlen('hi'); // " : / " $d = namespace\MYCONST; // "namespace __NAMESPACE__ ” $d = __NAMESPACE__ . '\MYCONST'; echo constant($d); // " " ?>

非常に分かりやすいコードですが、PHP定義のネーミングスペースは上のコードからどのようなものかがわかりますが、筆者個人的にはその定義は非常に逆人間だと思いますが、ネーミングスペースパスを逆スラッシュで区切っています.ただし、PHPまたはphpという名前のネーミングスペース、およびこれらの名前で始まるネーミングスペース(例えば、PHPClasses)は、ユーザースペースのコードではなく言語カーネルとして使用されるように保持されることに注意してください.
ネーミングスペースの定義
PHPネーミングスペース機能はPHP 5のみである.3.0以降では、クラス、インタフェース、関数、定数のみがネーミングスペースに含まれます.
1;
class Connection { /* ... */ }
function connect() { /* ... */ }
?>

もちろん、このようにすべての必要な内容を括弧で含めることもできます.
'UTF-8');
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { //     
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

しかし、これはインデント上の問題を引き起こしやすいので、筆者は使用をお勧めしません.また、一般的には、1つのファイルにクラスが含まれているので、カッコを使ってネーミングスペースの範囲を分割する必要はありません.
ネームスペースの使用
ネーミングスペースパスには3つの形式が存在します
非限定名、または接頭辞を含まないクラス名.例えば$a=new foo();またはfoo::staticmethod();.現在のネーミングスペースがcurrentnamespaceの場合、fooはcurrentnamespacefooとして解析されます.fooを使用するコードがグローバルで、任意のネーミングスペースに含まれないコードである場合、fooはfoo`として解析されます.
$a=new subnamespacefoo();またはsubnamespacefoo::staticmethod();.現在のネーミングスペースがcurrentnamespaceの場合、fooはcurrentnamespacesubnamespacefooとして解析されます.fooのコードがグローバルで、任意のネーミングスペースに含まれていないコードを使用すると、fooはsubnamespacefooとして解析されます.
完全に名前を限定するか、$a=newcurrentnamespacefoo()などのグローバル接頭辞オペレータを含む名前.またはcurrentnamespacefoo::staticmethod();.この場合、fooは常にコード内の文字名(literal name)currentnamespacefooとして解析される.
PHP自体の動的言語の特性のため、文字列を使用してネーミングスペース内の要素に動的にアクセスすることができます.

namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"
"
; } } function funcname() { echo __FUNCTION__,"
"
; } const constname = "namespaced"; include 'example1.php'; $a = 'classname'; $obj = new $a; // prints classname::__construct $b = 'funcname'; $b(); // prints funcname echo constant('constname'), "
"
; // prints global /* note that if using double quotes, "\
amespacename\\classname" must be used */
$a = '
amespacename\classname'
; $obj = new $a; // prints namespacename\classname::__construct $a = 'namespacename\classname'; $obj = new $a; // also prints namespacename\classname::__construct $b = 'namespacename\funcname'; $b(); // prints namespacename\funcname $b = '
amespacename\funcname'
; $b(); // also prints namespacename\funcname echo constant('
amespacename\constname'
), "
"
; // prints namespaced echo constant('namespacename\constname'), "
"
; // also prints namespaced ?>

ただし、一重引用符の違いに注意してください.一重引用符はの変換処理を必要とせず、二重引用符は等変換記号を使用しなければなりません.
Java言語はimportメカニズムを使用してネーミングスペースを導入し、Javaはクラス名を指定できるため、Javaは最大で特定のクラスにしかインポートできませんが、PHPは1つのネーミングスペース内のクラス、定数、メソッドなどに指定でき、ネーミングスペース別名をサポートします.

namespace foo;
use My\Full\Classname as Another;
//        use My\Full\NSname as NSname   
use My\Full\NSname;
//        
use ArrayObject;
// importing a function (PHP 5.6+)
use function My\Full\functionName;
// aliasing a function (PHP 5.6+)
use function My\Full\functionName as func;
// importing a constant (PHP 5.6+)
use const My\Full\CONSTANT
$obj = new namespace\Another; //     foo\Another   
$obj = new Another; //     My\Full\Classname   
NSname\subns\func(); //      My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); //     ArrayObject   
//       "use \ArrayObject" ,       foo\ArrayObject   
func(); // calls function My\Full\functionName
echo CONSTANT; // echoes the value of My\Full\CONSTANT
?>

名前解析規則
まず、前述した3つの名前タイプについて説明します.名前解析は次のルールに従います.
名前を完全に限定する関数、クラス、定数の呼び出しはコンパイル時に解析されます.例えばnewABはクラスABとして解析される.
すべての非限定名と限定名(非完全限定名)は、現在のインポートルールに従ってコンパイル時に変換されます.たとえば、ネーミングスペースABCがCにインポートされると、CDe()の呼び出しがABCDe()に変換されます.
ネーミングスペース内では、インポートルールに従って変換されていないすべての限定名に、現在のネーミングスペース名が加算されます.たとえば、ネーミングスペースABの内部でCDe()が呼び出されると、CDe()はABCDe()に変換されます.
非限定クラス名は、現在のインポートルールに従ってコンパイル時に変換されます(短いインポート名の代わりにフルネームが使用されます).たとえば、ネーミングスペースABCがCにインポートされた場合、new C()はnew ABC()に変換されます.
ネーミングスペースの内部(ABなど)では、非限定名の関数呼び出しは実行時に解析されます.たとえば、関数foo()の呼び出しは、次のように解析されます.
現在のネーミングスペースでABfoo()という関数を検索
グローバル空間の関数foo()を検索して呼び出してみます.
非限定名または限定名クラス(非完全限定名)の呼び出しは、ネーミングスペース(例えばAB)内で実行時に解析されます.次に、new C()およびnew DE()を呼び出す解析手順を示します.
新C()の解析:
現在のネーミングスペースでABCクラスを検索します.
クラスABCを自動マウントしてみます.
新DE()の解析:
クラス名の前に現在のネーミングスペース名を付けると、ABDEとなり、クラスが検索されます.
クラスABDEを自動マウントしてみます.
グローバルネーミングスペース内のグローバルクラスを参照するには、完全限定名newC()を使用する必要があります.
上のルールから見ると、実際にPHPの導入ルールはJavaと少し似ていますが、Javaは完全にオブジェクト向けなので、PHPは本質的にオブジェクトベースの言語にすぎません.
クラスの自動ロード
初期のPHP開発では、開発者が最も煩わしいのはinclude関数の山にファイルがたくさん含まれていることであり、初期の頃はPHPがオブジェクト向けの概念が確かに悪かった.PHPはスクリプト言語としてプログラムエントリが存在しないため、スクリプトの順序化実行の誘惑力は本当に大きく、オブジェクト向け開発でも、しかし,優れたモジュール分割導入メカニズムが欠けており,コードは美しさが難しいといえるが,最大の代表はWordpressである.この典型的なプロジェクトを見たことがある友人は、さまざまな初期化、ビジネスプロセスがそれぞれの異なるファイルに分散しているため、include関数を使用して接続し、ページレンダリングのたびに同じプロセスを実行します.もちろん、これはWordpressの歴史的な負担ですが、古いバージョンのPHPをサポートしている場合、Wordpressコードは十分に最適化されています.
PHP 5では、1つの__を定義できるので、そんなに面倒な必要はありません.Autoload()関数は、定義されていないクラスを呼び出すと起動し、エラーを投げ出す前に最後の救済を行いますが、この関数の本意は完全に曲解され、現在は自動ロードに使用されています.
この関数は実際には推奨されていませんが、逆にspl_を使用する必要があります.autoload_register()は、クラスの自動ロード関数を登録します.
bool spl_autoload_register ([ callable autoloadfunction[,bool throw = true [, bool $prepend = false ]]] ) autoload_functionは登録が必要な自動マウント関数で、これが空の場合spl_が登録されます.Autoload関数、
throwこのパラメータにautoload_が設定されていますfunctionが正常に登録できなかった場合、spl_autoload_register()が異常を投げ出すかどうか.
prependがtrueならspl_autoload_register()は、キューの末尾ではなく、キューの先頭に関数を追加します.
spl_についてお話ししましたAutoload関数は、実際に関数を登録する仕様に従います.関数は次のように宣言されます.
void spl_Autoload(string classname[,string file_extensions])この関数のデフォルト実装はC言語を通過するため、ここではPHP言語の実装仕様を与える.

// Your custom class dir
define('CLASS_DIR', 'class/')
// Add your class dir to include path
set_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);
// You can use this trick to make autoloader look for commonly used "My.class.php" type filenames
spl_autoload_extensions('.class.php');
// Use default autoload implementation
spl_autoload_register();
?>function __autoload(){
$dir = './libralies';
set_include_path(get_include_path(). PATH_SEPARATOR. $dir);
$class = str_replace('\\', '/', $class) . '.php'; 
require_once($class);
}

ネーミングスペースパスを実際のパスに置き換えます.