ホームページ >バックエンド開発 >PHPチュートリアル >PHPのオートロードの仕組みを詳しく解説

PHPのオートロードの仕組みを詳しく解説

WBOY
WBOYオリジナル
2016-07-25 09:07:291058ブラウズ
  1. /* person.class.php */
  2. class Person {
  3. public $name;
  4. function __construct ($name, $age)
  5. {
  6. $this- >name = $name;
  7. $this->age = $age; }
  8. }
  9. ?>
  10. /* no_autoload.php */
  11. require_once (" ; require_once を使用してそれを含めるクラス。その後、 Person クラスを直接使用してオブジェクトをインスタンス化できます。 ただし、プロジェクトの規模が拡大し続けると、この方法を使用するといくつかの隠れた問題が発生します:
  12. PHP ファイルで他の多くのクラスを使用する必要がある場合、多くの require/include ステートメントが必要になり、不必要なクラス ファイルが省略またはインクルードされる可能性があります。
  13. 多数のファイルで他のクラスを使用する必要がある場合、各ファイルに正しいクラス ファイルが含まれていることを確認するのは間違いなく悪夢のような作業になります。
  14. PHP5 は、クラスの自動読み込み (オートロード) メカニズムというこの問題の解決策を提供します。
オートロードメカニズムにより、PHP プログラムは最初からすべてのクラスファイルを含めるのではなく、クラスが使用される場合にのみクラスファイルを自動的に含めることができます。このメカニズムは遅延ロードとも呼ばれます。 以下は、自動ロードメカニズムを使用して Person クラスをロードする例です。

/* autoload.php */

function __autoload($classname) {

require_once ($classname . "class.php")

}

$person = new Person(" Altair", 6);

var_dump ($person);
?>
  1. コードをコピー
  2. 通常、PHP5 がクラスを使用するときに、クラスがロードされていないことが判明すると、自動的に __autoload() 関数が実行され、使用する必要があるクラスをロードできます。

    この簡単な例では、拡張子「.class.php」が付いたクラス名を直接追加してクラス ファイル名を形成し、require_once を使用してそれをロードします。

    この例から、autoload は少なくとも 3 つのことを実行する必要があることがわかります。

    最初に、クラス名に基づいてクラスファイル名を決定します。

    2 番目のことは、クラス ファイルが配置されているディスク パスを決定することです (この場合は最も単純なケースで、クラスはそれらを呼び出す PHP プログラム ファイルと同じフォルダーにあります)。

    3 番目のことは、クラスをディスク ファイルからシステムにロードすることです。 3 番目のステップは最も単純で、include/require を使用するだけです。

    第 1 ステップと第 2 ステップの機能を実現するには、クラス名とディスク ファイル間のマッピング方法を開発中に合意する必要があります。この方法でのみ、クラス名に基づいて対応するディスク ファイルを見つけることができます。

    したがって、含めるクラス ファイルが多数ある場合は、対応するルールを決定し、__autoload() 関数でクラス名と実際のディスク ファイルを一致させるだけで、遅延読み込み効果を実現できます。

    ここから、 __autoload() 関数の実装で最も重要なことは、クラス名と実際のディスク ファイルの間のマッピング ルールの実装であることもわかります。

    しかし、ここで問題が発生します。システムの実装で他の多くのクラス ライブラリを使用する必要がある場合、これらのクラス ライブラリは異なる開発者によって作成され、クラス名と実際のディスク ファイル間のマッピング ルールが異なる可能性があります。現時点で、クラス ライブラリ ファイルの自動ロードを実装したい場合は、すべてのマッピング ルールを __autoload() 関数に実装する必要があります。この場合、__autoload() 関数は非常に複雑になるか、実装が不可能になる可能性があります。最終的に、__autoload() 関数は、たとえ実装できたとしても非常に肥大化する可能性があり、将来のメンテナンスとシステム効率に大きな悪影響を及ぼします。この場合、もっとシンプルで明確な解決策はないのでしょうか?答えはもちろん「いいえ」です!

    さらなるソリューションを検討する前に、まず PHP の自動ロード メカニズムがどのように実装されているかを見てみましょう。

    2. PHPのオートロード機構の実装

    PHP がオブジェクトをインスタンス化するとき (実際にはインターフェイスを実装するとき、クラスでクラス定数や静的変数を使用するとき、またはクラスで静的メソッドを呼び出すとき)、まずクラス (またはインターフェイス) がシステムに存在するかどうかを確認します。存在しない場合は、自動ロード メカニズムを使用してクラスをロードしてみてください。 自動ロードメカニズムの主な実行プロセスは次のとおりです。 (1) エグゼキュータのグローバル変数関数ポインタ autoload_func が NULL かどうかを確認します。 (2) autoload_func==NULL の場合、__autoload() 関数がシステムに定義されているかどうかを確認します。定義されていない場合は、エラーを報告して終了します。 (3) __autoload() 関数が定義されている場合は、__autoload() を実行してクラスのロードを試み、ロード結果を返します。 (4) autoload_func が NULL でない場合は、autoload_func ポインタが指す関数を直接実行してクラスをロードします。この時点では、__autoload() 関数が定義されているかどうかはチェックされないことに注意してください。

    PHP には、自動読み込みメカニズムを実装するための 2 つのメソッドが用意されています:

    前に説明した 1 つの方法は、通常は PHP ソース プログラムに実装されるユーザー定義の __autoload() 関数を使用することです。

    もう 1 つは、関数を設計し、autoload_func ポインターをその関数に指定することです。これは通常、C 言語を使用して PHP 拡張機能で実装されます。

    __autoload() 関数と autoload_func の両方が実装されている場合 (autoload_func が特定の PHP 関数を指す)、autoload_func 関数のみが実行されます。

    3. SPL オートロードメカニズムの実装

    SPLはStandard PHP Libraryの略称です。 これは、PHP5 で導入された拡張ライブラリです。その主な機能には、オートロード メカニズムとさまざまな Iterator インターフェイスまたはクラスの実装が含まれます。

    SPL オートロード メカニズムは、関数ポインター autoload_func をオートロード関数を備えた自己実装関数にポイントすることによって実装されます。

    SPL には spl_autoload と spl_autoload_call という 2 つの異なる関数があり、autoload_func をこれら 2 つの異なる関数アドレスに指定することで、異なる自動ロード メカニズムが実装されます。

    spl_autoload は SPL によって実装されるデフォルトの自動ロード関数であり、その機能は比較的単純です。

    最初のパラメータはクラス名を表す $class_name で、2 番目のパラメータ $file_extensions はオプションであり、クラス ファイルの拡張子を表します。 $file_extensions には複数の拡張子を指定でき、拡張子名はセミコロンで区切ることができます。指定しない場合は、デフォルトの拡張子 .inc または .php が使用されます。

    spl_autoload は、まず $class_name を小文字に変更し、次にすべてのインクルード パスで $class_name.inc または $class_name.php ファイルを検索し ($file_extensions パラメーターが指定されていない場合)、見つかった場合はクラス ファイルをロードします。

    spl_autoload("person", ".class.php") を手動で使用して Person クラスをロードできます。実際、複数の拡張子を指定できる点を除けば、require/include に似ています。

    spl_autoload を自動的に動作させる、つまり autoload_func を spl_autoload にポイントする方法は?答えは、spl_autoload_register 関数を使用することです。 PHP スクリプトで初めてパラメータを指定せずに spl_autoload_register() を呼び出すと、autoload_func を spl_autoload に指定できます。

    上記の説明を通じて、spl_autoload の機能は比較的単純であり、SPL 拡張機能で実装されており、その機能を拡張できないことがわかりました。独自のより柔軟な自動読み込みメカニズムを実装したい場合はどうすればよいでしょうか?この時点で、spl_autoload_call 関数がデビューします。

    まず spl_autoload_call 実装の素晴らしい機能を見てみましょう。 SPL モジュール内には、本質的に HashTable であるグローバル変数 autoload_functions がありますが、リンク リスト内の各要素は、次の機能を持つ関数を指す関数ポインターであると単純に考えることができます。クラスの自動ロード機能。 spl_autoload_call の実装自体は非常に単純で、リンクされたリスト内の各関数を順番に実行し、各関数の実行後に必要なクラスがロードされたかどうかを判断し、ロードが成功した場合はそのままリターンします。リンクされたリストの他の機能を実行し続けます。このリンクされたリスト内のすべての関数が実行された後でクラスがロードされていない場合、spl_autoload_call はユーザーにエラーを報告せずに直接終了します。したがって、オートロード メカニズムを使用しても、クラスが自動的に正しくロードされることは保証されません。キーはオートロード関数の実装方法に依存します。

    では、自動ロード関数リスト autoload_functions は誰が管理しているのでしょうか?

    先ほど述べた spl_autoload_register 関数です。ユーザー定義のオートロード関数をこのリンク リストに登録し、autoload_func 関数ポインタを spl_autoload_call 関数にポイントすることができます。 spl_autoload_unregister 関数を使用して、登録された関数を autoload_functions リンク リストから削除することもできます。

    前のセクションで述べたように、autoload_func ポインターが null でない場合、__autoload() 関数は自動的に実行されません。autoload_func は spl_autoload_call を指しており、それでも __autoload() 関数を機能させたい場合はどうすればよいでしょうか。 ?もちろん、引き続き spl_autoload_register(__autoload) 呼び出しを使用して、autoload_functions リンク リストに登録します。

    最初のセクションの最後の質問に戻ると、解決策があります。各クラス ライブラリの異なる命名メカニズムに従って独自のオートロード関数を実装し、spl_autoload_register を使用してそれらを SPL オートロード関数キューにそれぞれ登録します。この方法では、非常に複雑な __autoload 関数を維持する必要がありません。

    4. オートロード効率の問題と対策

    オートロード メカニズムを使用するとき、多くの人が最初に抱く反応は、オートロードを使用するとシステムの効率が低下するというもので、効率性のためにオートロードを使用しないことを提案する人もいます。

    オートロード実装の原理を理解すると、オートロード メカニズム自体がシステム効率に影響を与える理由ではないことがわかります。これにより、システムに不要なクラスがロードされなくなるため、システム効率が向上する可能性さえあります。

    では、なぜ多くの人は自動ロードを使用するとシステム効率が低下するという印象を持っているのでしょうか?

    実際、オートロードメカニズムの効率に影響を与えるのは、ユーザーが設計したオートロード機能です。

    クラス名と実際のディスク ファイルを効率的に一致させることができない場合 (これはファイル名だけでなく実際のディスク ファイルを指すことに注意してください)、システムはファイルが存在するかどうかを大量にチェックする必要があります (これには、パスに含まれる各インクルード パスでチェックされます)、ファイルが存在するかどうかを判断するにはディスク I/O 操作が必要です。ご存知のとおり、ディスク I/O 操作の効率は非常に低いため、これがパフォーマンスを低下させる原因となります。オートロードメカニズムの効率性!

    したがって、システムを設計するときは、クラス名を実際のディスク ファイルにマッピングするための明確なメカニズムを定義する必要があります。このルールが単純かつ明確であればあるほど、自動ロード メカニズムはより効率的になります。

    結論: オートロード メカニズムは本質的に非効率的ではありません。オートロードの乱用や不適切に設計されたオートロード機能のみが効率の低下につながります。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。