ホームページ >バックエンド開発 >PHPチュートリアル >Phalcon自動ローディング(PHP自動ローディング)

Phalcon自動ローディング(PHP自動ローディング)

WBOY
WBOYオリジナル
2016-06-23 13:18:391040ブラウズ

自動読み込み(palconLoader)

転載する場合はソースを明記してください

1. PHPファイルの紹介

include() または require() 関数を使用して、ファイルの内容をファイルの前に挿入できます。 PHPプログラムが実行されます。

違い: エラーの処理方法が異なります。 include() 関数warning を生成します (ただし、スクリプトは実行を継続します) が、require() 関数は 致命的エラー を生成します (エラー発生後にスクリプトは実行を停止します)

* ファイルが存在しないか名前が変更されている場合、スクリプトは実行を続行しないため、include() の代わりに require() を使用することをお勧めします。

2. PHP クラスの自動ロード

参考記事: PHP マニュアルおよび PHP の自動クラスロード機構

php5 より前では、各 PHP フレームワークは、一般に、特定の取り決めに従って実装する必要があります。自動ロードは条件に一致する File クラスまたは関数に準拠します。したがって、php5 より前のクラスの使用は現在ほど頻繁ではありませんでした。

php5 以降、php クラスをロードするときに、クラスが配置されているフォルダーが含まれていない場合、またはクラス名が間違っている場合、Zend エンジンは自動的に

__autoload 関数

を呼び出します。 __autoload 関数はユーザーが実装する必要があります。 バージョンphp5.1.2以降では、

spl_autoload_register関数

を使用して負荷処理関数をカスタマイズできます。この関数が呼び出されない場合、spl のカスタム spl_autoload 関数がデフォルトで使用されます。 1. PHP の自動ロード __autoload

function __autoload($className) {    $file = $className . '.php';    if (is_file($file)) {        require($file);    }else{        echo 'no this ' . $className . ' class file';    }}$demo = new Demo();

実際、__autoload は少なくとも 3 つのこと (「3 つのステップ」) を実行する必要があることがわかります。

クラス名に基づいてクラス ファイルを決定します。
  1. クラス ファイルが配置されているパスを決定します。上の例では、テスト ファイルは実際には同じディレクトリにあります。
  2. 指定されたクラスを含むファイルをプログラムにロードします。
  3. 最初と 2 番目のステップでは、クラス名とファイルの
マッピング方法

について合意する必要があります。この方法でのみ、クラス名に基づいて対応するファイルを見つけてロードを実装できます。 したがって、__autoload の自動ロードで最も重要なことは、

クラス名とそれが配置されているファイルの対応を指定することです

。含める必要があるクラスが多数ある場合は、対応するルールを確立し、クラス名を対応するファイルにマップして、遅延読み込みを実現するだけです。

ヒント: spl_autoload_register() は、クラスの自動ロードを実装するためのより柔軟な方法を提供します。したがって、__autoload() 関数の使用は推奨されなくなり、将来のバージョンでは非推奨になる可能性があります。

2. PHP 自動ロード spl_autoload_register

はじめに: PHP システム実装で他の多くのクラス ライブラリが使用されている場合、これらのクラス ライブラリは異なるエンジニアによって開発される可能性があるため、クラス名はそれが配置されているファイルとは異なります。マッピング規則は異なります。この時点で、クラス ライブラリの自動ロードを実装する場合は、すべてのマッピング ルールを __autoload 関数に実装する必要があります。これにより、__autoload が非常に複雑になったり、実装が不可能になったりします。同時に、__autoload 関数も非常に肥大化します。これは、将来のシステムの保守とパフォーマンスに多大な悪影響を及ぼします。 (

__autoload の欠点

) spl_autoload_register:

指定された関数を __autoload の実装として登録します。簡単に言うと、関数は SPL の __autoload 関数スタックに登録され、システムのデフォルトの __autload() 関数が削除されます。

なるほど

ヒント:

__autoload() 関数がプログラムに実装されている場合は、__autoload() キューに
    明示的に登録
  1. する必要があります。 spl_autoload_register() 関数は、Zend Engine の __autoload() 関数を spl_autoload() または spl_autoload_call() に置き換えるためです。
  2. 一度しか定義できない __autoload との比較。 spl_autoload_register() 関数は、
  3. 複数の自動ロード関数を定義

    できます。 spl_autoload_register はオートロード関数キューを作成するため、キューは定義された順序で 1 つずつ実行されます。

    function __autoload($className) {      echo 'autload class:', $className, '<br />';  }  function classLoader($className) {      echo 'SPL load class:', $className, '<br />';  }  spl_autoload_register('classLoader');  new Test();//结果:SPL load class:Test 

関数の説明

 function __autoload($className) {       echo 'autload class:' . $className . '<br />';   }   function classLoader($className) {       echo 'SPL load class:' . $className . '<br />';   }   spl_autoload_register('classLoader');   $demo = new Demo();//结果:SPL load class:Demo

autoload_function [オプション] 自動ロード スタックに追加される関数。デフォルトは spl_autoload() です。
  • 関数に文字列名を指定する代わりに、spl_autoload_register() 関数を呼び出してコールバック関数を登録することもできます。たとえば、array('class','method') のような配列を指定すると、
      オブジェクトのメソッドを使用する
    • ことができます。
    throw [オプション] 登録が成功しない場合に例外をスローするかどうか
  • prepend [オプション] 関数をキューの末尾ではなくキューの先頭に追加するかどうか。
注: SPL オートロード関数は、spl_autoload()、spl_autoload_register()、spl_autoload_functions()、spl_autoload_extensions()、および spl_autoload_call() 関数によって提供されます。

三、Phalcon的类自动加载

Phalcon\Loader 通用类加载器(Universal Class Loader),意在根据协议帮助项目自动加载项目中的类(This component helps to load your project classes automatically based on some conventions)。Phalcon支持四种类加载方式,先后顺序分别是注册类名、注册命名空间、注册前缀和注册文件夹的方式。

Phalcon的默认文件后缀为php,当然你自己也可以配置(setExtensions())。

1 . 注册类名

<?php$loader = new \Phalcon\Loader();$loader->registerClasses(    array(        "Some"         => "library/OtherComponent/Other/Some.php",        "Example\Base" => "vendor/example/adapters/Example/BaseClass.php",    ));$loader->register();    // i.e. library/OtherComponent/Other/Some.php$some = new Some();
  1. 最快的自动方法
  2. 不利于维护

具体实现:

  1. 判断是否有类被注册。
  2. 判断需要加载的类是否被注册,如果已注册则加载其对应路径文件。

2. 注册命名空间

<?php$loader = new \Phalcon\Loader();$loader->registerNamespaces(    array(       "Example\Base"    => "vendor/example/base/",       "Example\Adapter" => "vendor/example/adapter/",       "Example"         => "vendor/example/",    ));$loader->register();// vendor/example/adapter/Some.php$some = new Example\Adapter\Some();

使用命名空间或外部库组织代码时,你可以利用注册命名空间的方式来自动加载其包含的库。

对于命名空间对应的路径,要其末尾加一个斜杠。

具体实现:

  1. 判断是否有命名空间被注册。
  2. 判断需要加载的类是否已以注册的命名开始。

    例如注册的命名空间为 "Example\Base" => "vendor/example/base/"

    "Example\Base"    => "vendor/example/base/" $test1 = new Example\Base\Test();// vendor/example/base/Test.php $test2 = new Example\Test();// 错误,无法加载。

    名称处理:1、去掉命名指定空间前缀。2、将命名空间分隔符 \转换成文件分隔符 /

  3. 依据文件拓展名构建完整的文件路径,并判断该文件是否存在,如该文件存在加载。

3. 注册前缀

<?php$loader = new \Phalcon\Loader();$loader->registerPrefixes(    array(       "Example_Base"     => "vendor/example/base/",       "Example_Adapter"  => "vendor/example/adapter/",       "Example_"         => "vendor/example/",    ));    $loader->register();    // vendor/example/adapter/Some.php$some = new Example_Adapter_Some();

类似于命名空间,从2.1.0开始phalcon将不再支持前缀。

具体实现:

  1. 判断是否有前缀被注册。
  2. 判断需要加载的类是否已以前缀开始命名。

    例如注册的前缀为 "Example_Base" => "vendor/example/base/"

    "Example_Base"    => "vendor/example/base/" $test1 = new Example_Base_Test();// vendor/example/base/Test.php $test2 = new Example_Test();// 错误,无法加载。

    名称处理:1、去掉类的前缀。2、将前缀分隔符 _转换成文件分隔符 /

  3. 依据文件拓展名构建完整的文件路径,并判断该文件是否存在,如该文件存在加载。

4. 注册文件夹

<?php$loader = new \Phalcon\Loader();    $loader->registerDirs(    array(        "library/MyComponent/",        "library/OtherComponent/Other/",        "vendor/example/adapters/",        "vendor/example/"    ));    $loader->register();    // i.e. library/OtherComponent/Other/Some.php$some = new Some();

可以自动加载注册目录下的类文件。但是该方法在性能方面并不被推荐,因为Phalcon将在个文件夹下大量查找与类名相同的文件。在使用注册目录自动加载时,要注意注册目录的相关性,即将重要的目录放在前面。

具体实现:

  1. 将类名中的前缀分隔符 _或是命名空间分隔符 \替换成文件夹分割符 /
  2. 判断是否有文件夹被注册。
  3. 依据文件后缀构建可能的文件路径

    例如注册的前缀为 "vendor/example/base/"

     $test = new Test();// vendor/example/base/Test.php

5. 修改当前策略(Modifying current strategies)

即为当前自动加载数据添加额外的值。

<?php// Adding more directories$loader->registerDirs(    array(        "../app/library/",        "../app/plugins/"    ),    true);

注册时添加第二个参数值true,使其与原数组合并。

6. 安全层(Security Layer)

没有进行任何安全检查的自动加载器,如下:

<?php//Basic autoloaderspl_autoload_register(function($className) {    if (file_exists($className . '.php')) {        require $className . '.php';    }});

假如我们没有进行任何安全检查时,如果误启了自动加载器,那么恶意准备的字符串就回作为参数访问程序中的重要文件。

<?php//This variable is not filtered and comes from an insecure source$className = '../processes/important-process';//Check if the class exists triggering the auto-loaderif (class_exists($className)) {    //...}

Phalcon的做法是删除任何无用的字符串,减少被攻击的可能性。

7. 自动加载事件

在下面的例子中,而不必使用类加载器,使我们获得调试信息的流程操作:

<?php$eventsManager = new \Phalcon\Events\Manager();$loader = new \Phalcon\Loader();$loader->registerNamespaces(array(       'Example\\Base' => 'vendor/example/base/',       'Example\\Adapter' => 'vendor/example/adapter/',       'Example' => 'vendor/example/'));//Listen all the loader events$eventsManager->attach('loader', function($event, $loader) {    if ($event->getType() == 'beforeCheckPath') {        echo $loader->getCheckedPath();    }});$loader->setEventsManager($eventsManager);$loader->register();

Phalcon自动加载支持以下事件:

  • beforeCheckClass,自动加载的过程开始前触发,当返回布尔假可以停止活动操作。
  • pathFound,当一个类装入器定位触发
  • afterCheckClass,自动加载的过程完成后触发。

8. 注意事项(Troubleshooting)

  1. 自动加载区分大小写。
  2. 命名空间或前缀的方式要比文件夹的方式要快得多。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。