Maison  >  Article  >  développement back-end  >  Explication détaillée de la fonction de chargement automatique de PHP

Explication détaillée de la fonction de chargement automatique de PHP

零到壹度
零到壹度original
2018-03-27 10:37:311556parcourir

Cet article est un résumé de la fonction de chargement automatique de PHP, couvrant la fonction de chargement automatique de PHP, l'espace de noms de PHP, les normes PSR0 et PSR4 de PHP, etc.

1. Fonction de chargement automatique PHP

L'origine de la fonction de chargement automatique PHP

Pendant le processus de développement PHP, si vous souhaitez introduire une classe de l'extérieur, vous utilisez généralement les méthodes include et require pour inclure le fichier qui définit la classe. Lorsque cela est développé à petite échelle, il n’y a pas de gros problème. Cependant, dans les grands projets de développement, l'utilisation de cette méthode entraînera des problèmes cachés : si un fichier PHP doit utiliser de nombreuses autres classes, alors de nombreuses instructions require/include seront nécessaires, ce qui peut entraîner des omissions ou des inclusions de fichiers de classe inutiles. . Si un grand nombre de fichiers nécessitent l'utilisation d'autres classes, ce sera un cauchemar de s'assurer que chaque fichier contient le bon fichier de classe, et require_once coûte cher.

PHP5 fournit une solution à ce problème, qui est le mécanisme de chargement automatique des classes. Le mécanisme de chargement automatique permet aux programmes PHP d'inclure automatiquement les fichiers de classe uniquement lorsque les classes sont utilisées, au lieu d'inclure tous les fichiers de classe depuis le début. Ce mécanisme est également appelé chargement différé.

En résumé, la fonction de chargement automatique apporte plusieurs avantages :

  1. Pas besoin d'utiliser le class before Include ou require

  2. exigera/inclura uniquement des fichiers lors de l'utilisation de classes, ce qui implémente un chargement paresseux et évite d'exiger/inclure des fichiers redondants.

  3. Il n'est pas nécessaire de prendre en compte l'adresse disque réelle de la classe introduite, réalisant la séparation des fichiers logiques et physiques.

  
Si vous souhaitez en savoir plus sur la fonction de chargement automatique en détail, vous pouvez consulter les informations :
Mécanisme de chargement automatique de classe PHP
Analyse de l'implémentation du mécanisme de chargement automatique de PHP

Fonction de chargement automatique PHP __autoload()

Habituellement, lors de l'utilisation d'une classe, PHP5 exécutera automatiquement la fonction _autoload(). personnalisé par nos soins dans le programme. Dans cette fonction, nous pouvons charger les classes que nous devons utiliser. Ce qui suit est un exemple simple :

<span style="font-size: 16px;">function __autoload($classname) {  <br>  require_once ($classname . "class.php"); <br>}<br></span>

Dans notre exemple simple, nous ajoutons directement le nom de la classe à l'extension ".class.php" pour former le nom du fichier de classe. utilisez require_once pour le charger. À partir de cet exemple, nous pouvons voir que le chargement automatique doit faire au moins trois choses :

  1. Déterminer le nom du fichier de classe en fonction du nom de la classe

  2. Déterminez le chemin du disque où se trouvent les fichiers de classe (dans notre cas, dans le cas le plus simple, les classes sont dans le même dossier que les fichiers du programme PHP qui appelez-les);

  3. Charge les classes à partir des fichiers disque dans le système.

La troisième étape est la plus simple, utilisez simplement include/require. Pour réaliser les fonctions des première et deuxième étapes, la méthode de mappage entre le nom de classe et le fichier disque doit être convenue lors du développement. Ce n'est qu'ainsi que nous pourrons trouver son fichier disque correspondant en fonction du nom de classe.

Lorsqu'il y a un grand nombre de fichiers de classe à inclure, il suffit de déterminer les règles correspondantes, puis dans la fonction __autoload(), de faire correspondre le nom de la classe avec le nom réel fichier disque, vous pouvez obtenir l'effet d'un chargement paresseux. De là, nous pouvons également voir que la chose la plus importante dans l'implémentation de la fonction _autoload() est l'implémentation des règles de mappage entre le nom de la classe et le fichier disque réel.

Problèmes avec la fonction __autoload()

Si vous devez utiliser de nombreuses autres bibliothèques de classes dans l'implémentation d'un système, ces bibliothèques de classes peuvent être écrits par différents développeurs et avoir des règles de mappage différentes entre les noms de classe et les fichiers disque réels. À l'heure actuelle, si vous souhaitez implémenter le chargement automatique des fichiers de bibliothèque de classes, vous devez implémenter toutes les règles de mappage dans la fonction __autoload(). Dans ce cas, la fonction autoload() peut être très compliquée, voire impossible à implémenter. En fin de compte, la fonction autoload() peut devenir très lourde. Même si elle peut être implémentée, elle aura un impact négatif important sur la maintenance future et l'efficacité du système.

Alors où est le problème ? Le problème est que _autoload() est une fonction globale qui ne peut être définie qu'une seule fois et n'est pas assez flexible. Par conséquent, toutes les règles logiques correspondant aux noms de classe et aux noms de fichiers doivent être implémentées dans une seule fonction, ce qui entraîne une surcharge de cette fonction. Alors comment résoudre ce problème ? La réponse est d'utiliser une pile d'appels _autoload, d'écrire différentes relations de mappage dans différentes fonctions _autoload, puis de les enregistrer et de les gérer de manière uniforme. Il s'agit du chargement automatique SPL introduit dans PHP5.

SPL Autoload

SPL est l'abréviation de Standard PHP Library. Il s'agit d'une bibliothèque d'extension introduite dans PHP5. Ses principales fonctions incluent l'implémentation du mécanisme de chargement automatique et de diverses interfaces ou classes Iterator. SPL Autoload a plusieurs fonctions spécifiques :

  1. spl_autoload_register : Enregistrer la fonction __autoload()

  2. spl_autoload_unregister : Désenregistrer les fonctions enregistrées

  3. spl_autoload_functions : Renvoie toutes les fonctions enregistrées

  4. spl_autoload_call : Essayez toutes les fonctions enregistrées pour charger une classe

  5. spl_autoload : Implémentation par défaut de __autoload()

  6. spl_autoload_extensions : enregistrez et renvoyez les extensions de fichiers par défaut utilisées par la fonction spl_autoload.


L'utilisation détaillée de ces fonctions peut être trouvée dans l'explication détaillée de spl_autoload en php

En termes simples, spl_autoload est SPL lui-même. La définition de la fonction __autoload() est très simple, il s'agit d'aller dans le répertoire enregistré (défini par set_include_path) pour trouver le fichier .php/.inc du même nom que $classname. Bien entendu, vous pouvez également spécifier des types spécifiques de fichiers en enregistrant des extensions (spl_autoload_exionsions).

Et spl_autoload_register() est la pile d'appels de chargement automatique que nous avons mentionnée ci-dessus. Nous pouvons enregistrer plusieurs de nos propres fonctions _autoload() dans cette fonction. Lorsque PHP ne trouve pas le nom de la classe Quand, PHP. appellera cette pile et appellera la fonction personnalisée _autoload() une par une pour réaliser la fonction de chargement automatique. Si nous n'entrons aucun paramètre dans cette fonction, alors la fonction spl_autoload() sera enregistrée.

D'accord, c'est la couche inférieure du chargement automatique de PHP. Le mécanisme d'enregistrement est déjà très flexible, mais que manque-t-il ? Comme nous l'avons dit ci-dessus, la clé du chargement automatique est le mappage des noms de classe et des fichiers. Différents frameworks ont des méthodes différentes pour cette relation de mappage. C'est très flexible, mais s'il est trop flexible, cela semblera compliqué. spécification pour cette relation de mappage, qui est PSR PSR0 et PSR4 dans la norme.

Mais avant de parler de PSR0 et PSR4, nous devons également comprendre le problème de l'espace de noms PHP, car ces deux standards ne visent pas réellement le mappage des noms de classes et des fichiers de répertoires, mais Est le mappage des espaces de noms et des fichiers. Pourquoi cela se produit-il ? D'après ma compréhension, l'idée PHP standard orientée objet, l'espace de noms est dans une certaine mesure un alias du nom de classe, alors pourquoi devrions-nous introduire l'espace de noms, et quels sont les avantages de l'espace de noms

2. Espace de noms


Pour comprendre l'espace de noms, jetez d'abord un œil à l'introduction de l'espace de noms dans la documentation officielle :

Qu'est-ce qu'un espace de noms ? D'une manière générale, un espace de noms est une façon d'encapsuler des choses. Ce concept abstrait se retrouve à de nombreux endroits. Par exemple, les répertoires sont utilisés dans les systèmes d'exploitation pour regrouper les fichiers associés et agissent comme des espaces de noms pour les fichiers du répertoire. Par exemple, le fichier foo.txt peut exister dans les répertoires /home/greg et /home/other en même temps, mais deux fichiers foo.txt ne peuvent pas exister dans le même répertoire. De plus, lors de l'accès au fichier foo.txt en dehors du répertoire /home/greg, nous devons mettre le nom du répertoire et le séparateur de répertoire avant le nom du fichier pour obtenir /home/greg/foo.txt. L'application de ce principe au domaine de la programmation est le concept d'espace de noms.
En PHP, les espaces de noms sont utilisés pour résoudre deux types de problèmes rencontrés lors de la création de code réutilisable tel que des classes ou des fonctions lors de l'écriture de bibliothèques de classes ou d'applications :
1 Code écrit par l'utilisateur et classes internes PHP Conflits de noms entre /fonctions/ constantes ou classes/fonctions/constantes tierces
2 Créer un nom (ou court) pour un nom d'identifiant très long (généralement défini pour atténuer le premier type de problème), améliorer la lisibilité du code source.
Les espaces de noms PHP fournissent un moyen de regrouper les classes, fonctions et constantes associées.

  
Pour faire simple, PHP n'autorise pas deux classes, fonctions ou noms de variables portant le même nom dans le programme, donc certaines personnes sont très confuses. ce n'est pas grave si tu n'as pas le même nom ? En fait, de nombreux grands programmes s'appuient sur de nombreuses bibliothèques tierces. Les conflits de noms ne devraient pas être trop fréquents. C'est le premier problème sur le site officiel. Alors comment résoudre ce problème ? Lorsqu'il n'y a pas d'espace de noms, le pauvre programmeur ne peut donner que le nom de classe a_b_c_d_e_f, où a/b/c/d/e/f a généralement sa propre signification spécifique, de sorte qu'il n'y aura généralement pas de conflits, mais ces noms de classe longs sont fatigants à écrire et encore plus inconfortables à lire. Par conséquent, PHP5 a introduit les espaces de noms. Le nom de la classe est le nom de la classe et l'espace de noms est l'espace de noms. Lorsque le programme est écrit/lu, le nom de la classe est utilisé directement lors de l'exécution, ce qui résout le problème.

De plus, les espaces de noms fournissent un moyen de regrouper les classes, fonctions et constantes associées. Il s'agit également d'une grande utilisation des espaces de noms de langage orienté objet. Les classes, variables et fonctions requises à des fins spécifiques sont écrites dans un espace de noms et encapsulées.

Après avoir résolu le problème des noms de classe, nous pouvons enfin revenir au standard PSR Alors, comment PSR0 et PSR4 standardisent-ils la relation de mappage entre les fichiers et les espaces de noms ? La réponse est : les restrictions sur le nom de l'espace de noms (enfin, c'est un peu déroutant), l'emplacement du répertoire du fichier de classe et la relation de mappage entre les deux. C'est le cœur de la norme. Une description plus complète peut être trouvée dans Modern PHP New Feature Series (1) - Namespace

3. PSR Standard


Avant de parler de PSR0 et PSR4, introduisons le standard PSR. L'inventeur et normalisateur du standard PSR est : PHP-FIG, et son site internet est : www.php-fig.org. C'est ce consortium qui a inventé et créé la spécification PSR. FIG est l'abréviation de Framework Interoperability Group. Il a été fondé en 2009 par plusieurs développeurs de frameworks open source. Depuis, de nombreux autres membres ont été sélectionnés. Bien qu'il ne s'agisse pas d'une organisation « officielle », elle représente également une grande partie de la communauté. . Le but de l'organisation est d'unifier les normes de codage de chaque projet avec le niveau de restrictions le plus bas pour éviter les problèmes liés au style de développement de chaque entreprise qui entrave le développement des concepteurs de programmes. Ainsi, tout le monde a inventé et résumé le PSR, PSR propose une recommandation de normes. (Proposition d'une recommandation de normes) Abréviation de Proposition de normes).

Pour des spécifications et des normes détaillées, vous pouvez consulter la
Spécification PSR en PHP

Standard PSR0

La spécification PRS-0 est le premier ensemble de spécifications publié. Elle formule principalement certaines normes de chargement automatique (la norme de chargement automatique PSR-0 a plusieurs exigences obligatoires :

).

1. Un espace de noms et une classe pleinement qualifiés doivent être conformes à la structure : "4aac54f4f8dd119027ebef8933d1fc35(d33850e6796f8b75fcb1883171968a6c)*7f2e8a8f95134d748fc1c6e95817954d"
2. Il existe un espace de noms de niveau supérieur (nom du fournisseur "Vendor Name")
3. Chaque espace de noms peut avoir plusieurs sous-espaces de noms
4 Lors du chargement à partir du système de fichiers, le délimiteur (/) de chaque espace de noms doit être. Convertir en DIRECTORY_SEPARATOR (séparateur de chemin du système d'exploitation)
5. Dans le nom de la classe, chaque symbole de trait de soulignement (_) doit être converti en DIRECTORY_SEPARATOR (séparateur de chemin du système d'exploitation). Dans un espace de noms, le symbole underscore_ n'a aucune signification (spéciale).
6. Lors du chargement à partir du système de fichiers, l'espace de noms et la classe qualifiés doivent se terminer par .php
7. Le nom Verdor, les espaces de noms et les noms de classe peuvent être composés de lettres majuscules et minuscules (sensibles à la casse)
.

  
Les règles spécifiques peuvent être un peu déroutantes, alors commençons par le début.

Jetons d'abord un coup d'œil au contenu général de la norme PSR0. Les articles 1, 2, 3 et 7 limitent les noms des espaces de noms, et les articles 4 et 5 définissent la relation de mappage entre les espaces de noms et les répertoires de fichiers. Il y a des restrictions, l'article 6 est le suffixe du nom du fichier.

Comme nous l'avons dit précédemment, comment la norme PSR standardise-t-elle la relation de mappage entre l'espace de noms et le répertoire de fichiers où il se trouve ? C'est en limitant le nom de l'espace de noms, l'emplacement du répertoire de fichiers et la relation de mappage entre les deux.

Ensuite, nous devrons peut-être nous demander, où est la restriction sur l'emplacement du répertoire où se trouve le fichier ? En fait, la réponse est :
  

Restreindre le nom de l'espace de noms + Restreindre le mappage du nom de l'espace de noms et du répertoire de fichiers = Restreindre le répertoire de fichiers

  
D'accord, réfléchissons-y d'abord Réfléchissez à ce sujet, pour un programme spécifique, s'il veut supporter le standard PSR0, quels ajustements doit-il faire ?

  1. Tout d'abord, le programme doit définir une fonction de mappage conforme aux articles 4 et 5 de la norme PSR0, puis enregistrer cette fonction dans spl_register( );

  2. Deuxièmement, lors de la définition d'un nouvel espace de noms, le nom de l'espace de noms et l'emplacement du répertoire du fichier doivent être conformes aux éléments 1, 2, 3, et 7.


Généralement, pour faciliter la maintenance du code, nous ne définirons qu'un seul espace de noms dans un fichier.

D'accord, nous avons le nom de l'espace de noms conforme à la norme PSR0. Grâce à la relation de mappage conforme à la norme PSR0, nous pouvons obtenir l'adresse du répertoire de fichiers conforme à la norme PSR0. correctement selon la norme PSR0, tout se passera bien, nécessite le fichier, nous pouvons utiliser l'espace de noms. N'est-ce pas étonnant ?

Ensuite, examinons en détail ce que spécifie la norme PSR0 ?

Prenons l'un des espaces de noms /Symfony/Core/Request, l'une des bibliothèques tierces Symfony dans laravel, comme exemple pour parler du standard PSR0 ci-dessus.
   

  1. Un espace de noms et une classe pleinement qualifiés doivent être conformes à la structure : "4aac54f4f8dd119027ebef8933d1fc35(d33850e6796f8b75fcb1883171968a6c)* < ; Class Name> »

/Symfony indiqué ci-dessus est le nom du fournisseur, qui est le nom de la bibliothèque tierce, et /Core est le nom de l'espace de noms, généralement des informations sur les attributs de notre espace de noms (par exemple, request est la fonction principale de Symfony ; enfin, Request est le nom de notre espace de noms). Cette spécification standard permet aux utilisateurs de voir très clairement la source et la fonction de l'espace de noms. , ce qui est propice au développement du code à maintenir.

2. Chaque espace de noms doit avoir un espace de noms de niveau supérieur (nom du fournisseur "Vendor Name")

C'est-à-dire que chaque espace de noms doit avoir un espace de noms de niveau supérieur similaire à /Symfony. Pourquoi y a-t-il une telle règle ? Parce que la norme PSR0 n'est responsable de la relation de mappage qu'après l'espace de noms de niveau supérieur, c'est-à-dire la partie de /Symfony/Core/Request, à laquelle le répertoire /Symfony doit être associé est défini par l'utilisateur ou le framework lui-même. Ce que l'on appelle l'espace de noms de niveau supérieur est un espace de noms avec des relations de mappage personnalisées, généralement le nom du fournisseur (le nom d'une bibliothèque tierce). En d’autres termes, l’espace de noms de niveau supérieur constitue la base du chargement automatique. Pourquoi les normes sont-elles fixées ainsi ? La raison est très simple. S'il existe un espace de noms /Symfony/Core/Transport/Request et qu'un autre espace de noms est /Symfony/Core/Transport/Request1, s'il n'y a pas d'espace de noms de niveau supérieur, nous devons écrire deux chemins et ces deux-là. Correspondant à l'espace de noms, que se passe-t-il s'il y a Request2 et Request3. Avec l'espace de noms de niveau supérieur /Symfony, nous n'avons besoin que d'un répertoire qui lui correspond, et le reste peut être analysé à l'aide du standard PSR.

3. Chaque espace de noms peut avoir plusieurs sous-espaces de noms

C'est très simple, Request peut être défini Il peut être défini comme /Symfony/Core/Request, ou il peut être défini comme /Symfony/Core/Transport/Request Il peut y avoir de nombreux sous-espaces de noms sous l'espace de noms /Core. Vous pouvez définir le nombre de couches d'espaces de noms. tu veux.

4. Lors du chargement depuis le système de fichiers, le délimiteur (/) de chaque espace de noms doit être converti en DIRECTORY_SEPARATOR ( Séparateur de chemin du système d'exploitation)

Nous arrivons enfin à la spécification de mappage. Le symbole / de l'espace de noms doit être converti en séparateur de chemin, ce qui signifie que l'espace de noms /Symfony/Core/Request doit être converti en une structure de répertoires telle que SymfonyCoreRequest.
  

5. Dans le nom de la classe, chaque symbole de soulignement _ doit être converti en DIRECTORYSEPARATOR (séparateur de chemin du système d'exploitation). Dans un espace de noms, le symbole de soulignement n'a aucune signification (spéciale).

Ce que cette phrase signifie, c'est que si notre espace de noms est /Symfony/Core/Request_a, alors nous devons le mapper à un répertoire comme SymfonyCoreRequesta. Pourquoi une telle disposition ? En effet, il n'y avait pas d'espace de noms avant PHP5 et les programmeurs ne pouvaient le nommer que Symfony_Core_Request_a. Cette disposition de PSR0 doit être compatible avec cette situation.
Les deux autres sont très simples et je n’entrerai pas dans les détails.
  
Avec de telles règles de dénomination d'espace de noms et normes de mappage, nous pouvons raisonner sur l'endroit où nous devrions placer les fichiers où se trouve l'espace de noms. En prenant toujours Symfony/Core/Request comme exemple, son répertoire est /path/to/project/vendor/Symfony/Core/Request.php, où /path/to/project est l'emplacement de votre projet sur le disque, /path /to /project/vendor est le répertoire où se trouvent toutes les bibliothèques tierces utilisées par le projet. /path/to/project/vendor/Symfony est le répertoire correspondant à l'espace de noms de niveau supérieur/Symfony. Les répertoires de fichiers ci-dessous sont établis conformément au standard PSR0 :

/Symfony/Core/Request => /Symfony/Core/Request.php

Tout est parfait, non ? Non, il y a encore quelques défauts :

  1. Faut-il quand même être compatible sans espaces de noms ?

  2. Selon la norme PSR0, l'espace de noms /A/B/C/D/E/F doit correspondre à une structure de répertoires /A/B/C /D/ E/F, cette structure de répertoires est-elle trop profonde ?

Norme PSR4

Fin 2013, la cinquième a été publié Spécification - PSR-4.

PSR-4 standardise la façon de spécifier un chemin de fichier pour charger automatiquement les définitions de classe, et standardise également l'emplacement des fichiers chargés automatiquement. À première vue, cela ressemble au PSR-0. En fait, ses fonctionnalités se chevauchent. La différence est que la spécification PSR-4 est relativement propre, supprimant le contenu compatible avec les versions précédentes de PHP 5.3 et ressemble un peu à une version améliorée de PSR-0. Bien entendu, le PSR-4 n'est pas destiné à remplacer complètement le PSR-0, mais à compléter le PSR-0 lorsque cela est nécessaire - bien sûr, le PSR-4 peut également remplacer le PSR-0 si vous le souhaitez. Le PSR-4 peut être utilisé avec d'autres mécanismes de chargement automatique, notamment le PSR-0.
La différence entre la norme PSR4 et la norme PSR0 :

  1. 在类名中使用下划线没有任何特殊含义。

  2. 命名空间与文件目录的映射方法有所调整。

对第二项我们详细解释一下 ( Composer自动加载的原理):
假如我们有一个命名空间:Foo/class,Foo 是顶级命名空间,其存在着用户定义的与目录的映射关系:

<span style="font-size: 16px;">"Foo/" => "src/"<br/></span>

按照PSR0标准,映射后的文件目录是: src/Foo/class.php,但是按照 PSR4 标准,映射后的文件目录就会是:src/class.php,为什么要这么更改呢?原因就是怕命名空间太长导致目录层次太深,使得命名空间和文件目录的映射关系更加灵活。

再举一个例子,来源 PSR-4——新鲜出炉的PHP规范:
PSR-0风格

<span style="font-size: 16px;">    vendor/<br>    vendor_name/<br>        package_name/<br>            src/<br>                Vendor_Name/<br>                    Package_Name/<br>                        ClassName.php       # Vendor_Name\Package_Name\ClassName<br>            tests/<br>                Vendor_Name/<br>                    Package_Name/<br>                        ClassNameTest.php   # Vendor_Name\Package_Name\ClassName<br></span>

  PSR-4风格

<span style="font-size: 16px;">    vendor/<br>    vendor_name/<br>        package_name/<br>            src/<br>                ClassName.php       # Vendor_Name\Package_Name\ClassName<br>            tests/<br>                ClassNameTest.php   # Vendor_Name\Package_Name\ClassNameTest<br></span>

对比以上两种结构,明显可以看出PSR-4带来更简洁的文件结构。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn