phpのネーミングスペースと自動ロードの実装
クラスの自動ロード
リード
phpコードにクラスをロードする場合は、includeまたはrequireのクラスファイルをロードする必要があります.しかし、次のような状況に遭遇しました.
もし私たちが一人の性別を判断する必要があるならば、男ならclass 1という類をインスタンス化し、女ならclass 2という類をインスタンス化します.では、このコードは、インスタンス化オブジェクトを1つ実行するたびに必要ですが、この2つのクラスファイルをロードする必要があります.
phpはこの問題に対して解決策を提案した.
この概念はphp 5にある.1で提案
使用法
では、この関数があればこう書きます.
プログラムの実行手順は次のとおりです.
ロード後loadという関数を実行し,classの接合により関数をロードする過程を完了した.
クラスの自動ロードについては、spl_について説明します.autoload_registerの時はもうみんなに話しました.今日はもう一つの__についてお話ししますAutoload()はphp 7ではもう推奨されていません
phpの_Autoload関数はマジック関数であり、この関数が現れる前にphpファイルに100個のオブジェクトが参照されている場合、このファイルはincludeまたはrequireを使用して100個のクラスファイルを導入する必要があり、phpファイルが膨大になります.そしてこれがありましたAutoload関数.
__Autoload関数はいつ呼び出されますか?phpファイルでnewキーを使用してオブジェクトをインスタンス化すると、クラスがこのphpファイルで定義されていない場合、__がトリガーされます.Autoload関数は,この場合,クラスを定義するphpファイルを導入することができ,その後,インスタンス化に成功する.
(注:インスタンス化されたオブジェクトが必要で、このファイルでクラスの定義が見つかっている場合、__autoload関数はトリガーされません)
彼とspl_autoload_registerの違いは、ファイルに同時に__が表示されることです.Autoloadとspl_autoload_registerの場合spl_autoload_レジスター基準
ネーミングスペース
私たちは以前クラスの自動ロードについて話したが、私は考えていた.
フレームワークでコードを書くとき、別のファイルで他のクラスを呼び出すたびに
げんり
なるほど、phpは5.3でネーミングスペースの概念を導入しました(これも多くのフレームワークが5.3以前のバージョンをサポートしていない理由の一つです)、ネーミングスペースは多少は知っているでしょう:知らない壁の隅の壁に行って考えたことがあります
ネーミングスペースは簡単に言えば識別であり、ネーミング競合の問題を解決することを主な目的としています.日常生活で同じ名前の人が多いように、どうやって区別するのでしょうか.では、追加の標識を付ける必要があります.職場を標識にするのはいいようだが、「名前をぶつける」気まずさを心配する必要はない.
ネーミングスペース分類完全限定ネーミングスペース 限定ネーミングスペース
現在のネーミングスペースに宣言がない場合、クラス名の制限と完全なクラス名の制限は等価です.スペースを指定しない場合、デフォルトはグローバル()です.
この例は,ネーミング空間において,限定クラス名と完全限定クラス名を用いる違いを示している.(完全修飾クラス名=現在のネーミングスペース+修飾クラス名)
ネーミングスペースを使用すると、クラス名に接頭辞を付けるだけで、競合が発生しにくく、自動インポートは行われません.
ファイルを導入しない場合、システムは「Class Not Found」エラーを投げ出す前に
上記の例は、関連ファイルを手動で導入した場合に実現されます.そうしないと、システムは「Class'成都徐大帥'not found」を投げ出します.彼女はこの書類がどこにあるか分からないからだ.ネーミングスペースの導入後に自動ロードが導入されました
次に、クラスをネーミングスペースでロードします.
ネーミングスペースを使用してクラスを自動的にロードする小さな実験
まず、新しいファイルで定義します.
これはもちろん重要ではありません.重要なのは私たちが彼の関数を呼び出すことです.同じディレクトリにindexを作成します.phpファイル(マッピング関係を書きさえすれば、異なるファイルでもいいです)
結果
クラス名とクラスアドレスのマッピング関係を用いて,自動ロードを実現した.しかし、これは、ファイルを追加するたびに、マッピングファイルを更新する必要があることを意味します.大きなシステムでは,このような配列が維持するマッピング関係は間違いなく面倒である.では、もっと良い方法はありませんか.
PSR 4自動ロード仕様
知らない子供の靴、ここPSR 4の中国語のドキュメントPSR 4の具体的な解釈を見ることができます下は上のリンクから抜粋して、私は上の2つの文章がすでに徹底的に話したと思います
例えば、全限定クラス名appviewnewsIndexにおいて、appがC:Baiduを表す場合、このクラスのパスはC:BaiduviewnewsIndexである.php
appviewnewsIndexの解析を例に、簡単なDemoを作成します.
このDemoからクラス名をパスに変換するプロセスを限定することが分かる.では、標準的なオブジェクト向け方式で自動ローダを実現しましょう.
まずファイルを作成します.php、appmvcviewhomeディレクトリにあります.
次に、ディレクトリにロードクラス(ネーミングスペースを必要としない)を作成します.
最後に、Loaderクラスのautoloadをspl_に登録します.autoload_register関数:
例のコードは、実際にはThinkPHP自動ローダのソースコードの簡略版であり、ThinkPHP 5が不活性なロードを実現する鍵である.
リード
phpコードにクラスをロードする場合は、includeまたはrequireのクラスファイルをロードする必要があります.しかし、次のような状況に遭遇しました.
require "Class1.php";
require "Class2.php";
$boy = $_GET['sex'] = 0?true:false;
if($boy)
{
$class1 = new Class1();
}else{
$class2 = new Class2();
}
もし私たちが一人の性別を判断する必要があるならば、男ならclass 1という類をインスタンス化し、女ならclass 2という類をインスタンス化します.では、このコードは、インスタンス化オブジェクトを1つ実行するたびに必要ですが、この2つのクラスファイルをロードする必要があります.
phpはこの問題に対して解決策を提案した.
spl_auto_register()
この概念はphp 5にある.1で提案
spl_auto_register($autoload_function = null, $throw = true, $prepend = false)
3
①autoload_function 【 】 , ( )。 ( ) , new include(requeire) , new 。 include require 。
② $throw autoload_function ,spl_autoload_register() 。
③ true, spl_autoload_register() , 。
使用法
では、この関数があればこう書きます.
function load($class)
{
require "./{$class}.php";
}
spl_autoload_register('load');
if($boy)
{
$class1 = new Class1();
}else{
$class2 = new Class2();
}
プログラムの実行手順は次のとおりです.
//
new --> -->
// spl_autoload_register
new --> --> spl_autoload_register -->
ロード後loadという関数を実行し,classの接合により関数をロードする過程を完了した.
__autoload()
クラスの自動ロードについては、spl_について説明します.autoload_registerの時はもうみんなに話しました.今日はもう一つの__についてお話ししますAutoload()はphp 7ではもう推奨されていません
phpの_Autoload関数はマジック関数であり、この関数が現れる前にphpファイルに100個のオブジェクトが参照されている場合、このファイルはincludeまたはrequireを使用して100個のクラスファイルを導入する必要があり、phpファイルが膨大になります.そしてこれがありましたAutoload関数.
__Autoload関数はいつ呼び出されますか?phpファイルでnewキーを使用してオブジェクトをインスタンス化すると、クラスがこのphpファイルで定義されていない場合、__がトリガーされます.Autoload関数は,この場合,クラスを定義するphpファイルを導入することができ,その後,インスタンス化に成功する.
(注:インスタンス化されたオブジェクトが必要で、このファイルでクラスの定義が見つかっている場合、__autoload関数はトリガーされません)
彼とspl_autoload_registerの違いは、ファイルに同時に__が表示されることです.Autoloadとspl_autoload_registerの場合spl_autoload_レジスター基準
ネーミングスペース
私たちは以前クラスの自動ロードについて話したが、私は考えていた.
フレームワークでコードを書くとき、別のファイルで他のクラスを呼び出すたびに
spl_autoload_register
という方法を書いていませんか?どうやって実現したの?げんり
なるほど、phpは5.3でネーミングスペースの概念を導入しました(これも多くのフレームワークが5.3以前のバージョンをサポートしていない理由の一つです)、ネーミングスペースは多少は知っているでしょう:知らない壁の隅の壁に行って考えたことがあります
ネーミングスペースは簡単に言えば識別であり、ネーミング競合の問題を解決することを主な目的としています.日常生活で同じ名前の人が多いように、どうやって区別するのでしょうか.では、追加の標識を付ける必要があります.職場を標識にするのはいいようだが、「名前をぶつける」気まずさを心配する必要はない.
ネーミングスペース分類
new \ (); //
new \ \ (); //
現在のネーミングスペースに宣言がない場合、クラス名の制限と完全なクラス名の制限は等価です.スペースを指定しない場合、デフォルトはグローバル()です.
namespace ;
new \ (); // \ \ ( )
new \ \ (); // \ ( )
この例は,ネーミング空間において,限定クラス名と完全限定クラス名を用いる違いを示している.(完全修飾クラス名=現在のネーミングスペース+修飾クラス名)
/* */
use \ ;
new (); // \ ( )
/* */
use \ AS CEO;
new CEO(); // \ ( )
/* */
new \ \ ();// \ ( )
ネーミングスペースを使用すると、クラス名に接頭辞を付けるだけで、競合が発生しにくく、自動インポートは行われません.
ファイルを導入しない場合、システムは「Class Not Found」エラーを投げ出す前に
__autoload()
またはspl_autoload_register
関数をトリガーし、限定クラス名をパラメータとして入力します.上記の例は、関連ファイルを手動で導入した場合に実現されます.そうしないと、システムは「Class'成都徐大帥'not found」を投げ出します.彼女はこの書類がどこにあるか分からないからだ.ネーミングスペースの導入後に自動ロードが導入されました
次に、クラスをネーミングスペースでロードします.
ネーミングスペースを使用してクラスを自動的にロードする小さな実験
まず、新しいファイルで定義します.
//School.php
namespace top;
class School
{
function __construct()
{
echo ' '.__CLASS__.' ';
}
}
これはもちろん重要ではありません.重要なのは私たちが彼の関数を呼び出すことです.同じディレクトリにindexを作成します.phpファイル(マッピング関係を書きさえすれば、異なるファイルでもいいです)
//index.php
spl_autoload_register(function ($class){
// class ,
$map = [
'top\\School'=>'./School.php'
];
$file = $map[$class];
//
if (file_exists($file))
include $file;
});
echo "
";
new top\School();
結果
top\School
クラス名とクラスアドレスのマッピング関係を用いて,自動ロードを実現した.しかし、これは、ファイルを追加するたびに、マッピングファイルを更新する必要があることを意味します.大きなシステムでは,このような配列が維持するマッピング関係は間違いなく面倒である.では、もっと良い方法はありませんか.
PSR 4自動ロード仕様
知らない子供の靴、ここPSR 4の中国語のドキュメントPSR 4の具体的な解釈を見ることができます下は上のリンクから抜粋して、私は上の2つの文章がすでに徹底的に話したと思います
\(\)*\
PSR-4 , ( )。 ( ), ( )。
例えば、全限定クラス名appviewnewsIndexにおいて、appがC:Baiduを表す場合、このクラスのパスはC:BaiduviewnewsIndexである.php
appviewnewsIndexの解析を例に、簡単なDemoを作成します.
$class = 'app\view
ews\Index';
/* */
$vendor_map = array(
'app' => 'C:\Baidu',
);
/* */
$vendor = substr($class, 0, strpos($class, '\\')); // [app]
$vendor_dir = $vendor_map[$vendor]; // [C:\Baidu]
$rel_path = dirname(substr($class, strlen($vendor))); // [/view/news]
$file_name = basename($class) . '.php'; // [Index.php]
/* */
echo $vendor_dir . $rel_path . DIRECTORY_SEPARATOR . $file_name;
このDemoからクラス名をパスに変換するプロセスを限定することが分かる.では、標準的なオブジェクト向け方式で自動ローダを実現しましょう.
まずファイルを作成します.php、appmvcviewhomeディレクトリにあります.
namespace app\mvc\view\home;
class Index
{
function __construct()
{
echo ' Welcome To Home ';
}
}
次に、ディレクトリにロードクラス(ネーミングスペースを必要としない)を作成します.
class Loader
{
/* */
public static $vendorMap = array(
'app' => __DIR__ . DIRECTORY_SEPARATOR . 'app',
);
/**
*
*/
public static function autoload($class)
{
$file = self::findFile($class);
if (file_exists($file)) {
self::includeFile($file);
}
}
/**
*
*/
private static function findFile($class)
{
$vendor = substr($class, 0, strpos($class, '\\')); //
$vendorDir = self::$vendorMap[$vendor]; //
$filePath = substr($class, strlen($vendor)) . '.php'; //
return strtr($vendorDir . $filePath, '\\', DIRECTORY_SEPARATOR); //
}
/**
*
*/
private static function includeFile($file)
{
if (is_file($file)) {
include $file;
}
}
}
最後に、Loaderクラスのautoloadをspl_に登録します.autoload_register関数:
include 'Loader.php'; //
spl_autoload_register('Loader::autoload'); //
new \app\mvc\view\home\Index(); //
/**
* : Welcome To Home
*/
例のコードは、実際にはThinkPHP自動ローダのソースコードの簡略版であり、ThinkPHP 5が不活性なロードを実現する鍵である.