Maison > Article > développement back-end > Explication détaillée du noyau PHP des classes et du code orienté objet
Quand je suis entré en contact avec PHP pour la première fois, j'ai utilisé une approche orientée processus pour créer des sites Web très simples pour le plaisir, et j'ai simplement écrit PHP L'empilement, l'évolutivité et la maintenabilité sont si médiocres qu'il est extrêmement gênant de changer la logique. Plus tard, j'ai découvert que PHP supportait l'orientation objet, et du coup j'ai senti que j'étais vraiment jeune et ignorant à cette époque. Après tout, PHP est implémenté en C, ce qui n'est pas surprenant.
Avant-propos :
De notre contact PHPAu départ, la première chose que nous rencontrons, ce sont les fonctions : fonctions d'opération sur tableau, fonctions d'opération sur chaîne, fonctions d'opération sur fichier, etc. Ces fonctions sont la base de notre utilisation de PHP, et elles constituent également la programmation orientée processus que PHP prend en charge depuis sa naissance. Orienté processus, il encapsule les fonctions une par une et résout les problèmes avec une idée modulaire.
La programmation orientée objet est supportée depuis PHP4. Cependant, le support orienté objet de PHP4 n'est pas parfait. À partir de PHP5, PHP a introduit un nouveau modèle objet (Object Model) et ajouté de nombreuses nouvelles fonctionnalités, notamment le contrôle d'accès, les classes abstraites et finales, les méthodes de classe, les méthodes magiques, les interfaces, le clonage d'objets et les astuces de type, etc. Et dans la version PHP5.3 récemment publiée, les espaces de noms, la liaison statique retardée et supplémentaires. Il existe deux méthodes magiques __callStatic() et __invoquer().
Alors, comment est-il implémenté au bas de PHP et quelle est sa structure ?
Un. Structure de classe
Un exemple de citation de TIPI :
class ParentClass { } interface Ifce { public function iMethod(); } final class Tipi extends ParentClass implements Ifce { public static $sa = 'aaa'; const CA = 'bbb'; public function __constrct() { } public function iMethod() { } private function _access() { } public static function access() { } }
Une classe parent ParentClass, une interface Ifce et une sous-classe Tipi sont définies ici. La sous-classe hérite de la classe parent ParentClass, implémente l'interface Ifce et possède une variable statique $sa, une constante de classe CA, une méthode publique, une méthode privée et une méthode statique publique. Comment ces structures sont-elles implémentées dans le moteur Zend ? Comment les méthodes de classe et les variables membres sont-elles stockées ? Contrôle d'accès, comment les membres statiques sont-ils marqués ?
Tout d'abord, regardons la structure de stockage interne de la classe :
En prenant quelques champs de la structure ci-dessus, nous analysons les performances du code PHP au début de l'article dans le noyau. Comme indiqué ci-dessous :
Nom du champ | Description du champ | Classe ParentClass | Interface Ifce | Classe Tipi |
nom | Nom de la classe | ParentClass | Ifce | Tipi |
type | catégorie | 2 (défini par l'utilisateur) | 2 (défini par l'utilisateur) | 2 (défini par l'utilisateur, 1 est le système construit- en classe) |
parent | Classe Parent | Vide | Vide | Classe Parent |
refcount | Nombre de références | 1 | 1 | 2 |
ce_flags | Type de classe | 0 | 144 | 524352 |
function_table | Liste des fonctions | Vide | function_name=iMethod | type=2 | fn_flags=258 | function_name=__construct | 2 | fn_flags=65800 nom_fonction=_access type=2 |function_name=access | type=2 | fn_flags=257 |
interfaces | Liste des interfaces | null | null | Le numéro d'interface de l'interface Ifce est 1 |
nom de fichier | Adresse du fichier de stockage | /tipi.php | /tipi.php | /ipi.php |
line_start | Nombre de lignes de départ de classe | 15 | 18 | 22 |
line_end | Nombre de lignes de fin de classe | 16 | 20 | 38 |
二。变量与成员变量
如PHP内核的存储机制(分离/改变)所介绍,
变量要么是定义在全局范围中,叫做全局变量,要么是定义在某个函数中, 叫做局部变量。
成员变量是定义在类里面,并和成员方法处于同一层次。如下一个简单的PHP代码示例,定义了一个类, 并且这个类有一个成员变量。
class Tipi { public $var; }
1.成员变量的访问:
访问这个成员变量当然是通过对象来访问。
2.成员变量的规则:
1.接口中不允许使用成员变量
2.成员变量不能拥有抽象属性
3.不能声明成员变量为final
4.不能重复声明属性
在声明类的时候初始化了类的成员变量所在的HashTable,之后如果有新的成员变量声明时,在编译时zend_do_declare_property。函数首先检查成员变量不允许的这4 条情况。
比如:.
class Tipi { public final $var; }
运行程序将报错,违反了第三条:Fatal error: Cannot declare property Tipi::$var final, the final modifier is allowed only for methods and classes in .. 这个错误由zend_do_declare_property函数抛出
三。函数与成员方法
成员方法从本质上来讲也是一种函数,所以其存储结构也和常规函数一样,存储在zend_function结构体中。
对于一个类的多个成员方法,它是以HashTable的数据结构存储了多个zend_function结构体。 和前面的成员变量一样,在类声明时成员方法也通过调用zend_initialize_class_data方法,初始化了整个方法列表所在的HashTable。 在类中我们如果要定义一个成员方法,格式如下:
class Tipi{ public function t() {echo 1; } }
除去访问控制关键字,一个成员方法和常规函数是一样的,从语法解析中调用的函数一样(都是zend_do_begin_function_declaration函数), 但是其调用的参数有一些不同,第三个参数is_method,成员方法的赋值为1,表示它作为成员方法的属性。 在这个函数中会有一系统的编译判断,比如在接口中不能声明私有的成员方法。 看这样一段代码:
interface Ifce { private function method(); }
S'il est exécuté directement, le programme signalera une erreur : Erreur fatale : Type d'accès pour la méthode d'interface Ifce::method() doit être omis dans Ce code correspond au code dans la zend_do_begin_function_declaration fonction.
Quatre. Similitudes et différences entre les méthodes (Fonction) et les fonctions (Méthode)
L'implémentation des fonctions a été introduite plus tôt. méthodes consiste à comparer De même, une série de logiques est mise dans une collection pour exécution, mais il existe de nombreuses différences dans l'utilisation des deux. Nous discutons ici de la mise en œuvre des deux. Du point de vue de l'implémentation, le code interne des deux est finalement interprété comme op_array, et il n'y a aucune différence dans son exécution (sauf si des modifications spécifiques à l'objet ou des méthodes telles que $this/self sont utilisées), et la différence entre les deux se reflète dans les deux Aspects :
1 C'est la mise en œuvre de la définition (enregistrement) ; 🎜>
2. C'est la mise en œuvre de l'appel
Implémentation de la méthode de définition (enregistrement) Les fonctions et méthodes sont enregistrées dans la variable compiler_globals pendant la phase de compilation, et toutes deux utilisent les mêmes fonctions de traitement du noyau zend_do_begin_function_declaration() et zend_do_end_function_declaration() pour terminer ce processus. Le contenu interne des deux sera finalement interprété et stocké sous forme d'un tableau op_codes, mais l'emplacement "monté" après compilation est différent, comme indiqué ci-dessous :
Localisation d'enregistrement des fonctions et méthodes en PHP
La différence dans l'emplacement et la nature de la définition détermine que les méthodes sont plus avancées que les fonctions Plus travail de vérification, les appels de méthode ont un OPCODE supplémentaire nommé ZEND_INIT_METHOD_CALL ,
La fonction consiste à enregistrer la méthode dans execute_data.fbc, puis vous pouvez utiliser la même fonction de traitementZEND_DO_FCALL_BY_NAME pour le traitement.
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!