phpのネーミングスペースと自動ロードの実装

6880 ワード

クラスの自動ロード
リード
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が不活性なロードを実現する鍵である.