Heim >Backend-Entwicklung >PHP-Tutorial >Wang Shuai: Ausführlicher PHP-Kernel (1) – Erkundung des Prinzips schwach typisierter Variablen

Wang Shuai: Ausführlicher PHP-Kernel (1) – Erkundung des Prinzips schwach typisierter Variablen

WBOY
WBOYOriginal
2016-08-08 09:21:111059Durchsuche

PHP ist eine einfache und leistungsstarke Sprache, die viele für das Web geeignete Sprachfunktionen bietet, einschließlich der schwachen Typisierung von Variablen. Mit dem schwachen Typisierungsmechanismus können Sie einer Variablen jede Art von Wert zuweisen.
PHP wird über die Zend Engine (im Folgenden als ZE bezeichnet) ausgeführt. ZE ist in C geschrieben und implementiert unten eine Reihe schwacher Mechanismen. Die Speicherverwaltung von ZE nutzt Optimierungsstrategien wie Copy-on-Write und Referenzzählung, um Speicherkopien bei der Neuzuweisung von Variablen zu reduzieren.

Im Folgenden erfahren Sie nicht nur das Prinzip der PHP-Schwachtypisierung, sondern schreiben auch über PHP-Erweiterungen und führen in die Bedienung von PHP-Variablen ein.

1. PHP-Variablentypen

PHP hat 8 Variablentypen:

  • Standardtypen: Boolescher Wert, Ganzzahl, Gleitkommazahl, Zeichenfolge
  • Komplexer Typ: Array-Array, Objekt
  • Spezieller Typ: Ressourcenressource

PHP überprüft den Variablentyp nicht streng und die Variable muss nicht angezeigt werden Typ und weist ihn direkt zur Laufzeit zu. Variablen können auch frei konvertiert werden. Wie im folgenden Beispiel kann $i ohne Implementierungsdeklaration jeder Werttyp zugewiesen werden.

[php] Ansicht Klarschrift

  1. $i = 1; //int $i = 'zeig mir das Geld'; //string $i = 0.02; // float $i = array(1, 2, 3); // array $i = new Exception('test', 123); $i = fopen('/tmp/aaa.txt', 'a') // Ressource ?>

Wenn Sie Wenn Sie das Prinzip schwacher Typen nicht genau verstehen, werden Sie beim Vergleich von Variablen Überraschungen erleben, die die Erwartungen übertreffen.

[php] Ansicht Klarschrift

  1. $str1 = null; $str2 = false; echo $str1==$str2 ? 'Gleich' : 'Nicht gleich'; $str3 = ''; $str4 = 0; str3==$str4 ? 'Gleich' : 'Nicht gleich' $str5= 0; >'Gleich''Nicht gleich'; Die oben genannten drei Ergebnisse sind alle gleich, da PHP beim Vergleich von Variablen intern eine Variablenkonvertierung durchführt. Wenn Sie möchten, dass Wert und Typ gleichzeitig ermittelt werden, verwenden Sie zur Bestimmung bitte drei = (z. B. $a===0). Vielleicht finden Sie es alltäglich, vielleicht finden Sie es erstaunlich, dann tauchen Sie mit mir bitte in den PHP-Kernel ein und erkunden Sie das Prinzip der PHP-Variablen. 2. Einführung in die Variablenspeicherung und Standardtypen Alle Variablen in PHP werden mit der Struktur zval implementiert. In Zend/zend.h können wir die Definition von zval sehen: [php] Ansicht Klarschrift
    1. typedef union _zvalue_value {     long lval;                 /* long value */     double dval;               /* double value */     struct {                            char *val;         int len;               /* dies wird immer für Strings eingestellt.*/     } str;                     /* String (hat immer Länge) */     HashTable *ht;             /* ein Array */     zend_object_value obj;     /* speichert einen Objekt-Store-Handle und Handler */  } zvalue_value;   

    属性名含义默认值
    refcount__gc表示引用计数1
    is_ref__gc表示是否为引用0
    value存储变量的值
    type变量具体的类型

    Wobei refcount__gc und is_ref__gc angeben, ob die Variable eine Referenz ist. Das Typfeld identifiziert den Typ der Variablen. Der Wert des Typs kann sein: IS_NULL, IS_BOOL, IS_LONG, IS_FLOAT, IS_STRING, IS_ARRAY, IS_OBJECT, IS_RESOURCE. PHP wählt basierend auf dem Typ aus, wie zvalue_value gespeichert wird.
    zvalue_value kann den Kern eines variablen schwachen Typs realisieren, der wie folgt definiert ist:

    [php] view Klarschrift

    1. typedef union _zvalue_value { long lval; /* long value */ double dval;                                                       🎜>/* double value */ struct { char *int len; /* string (hat immer eine Länge) */ HashTable *ht; /* ein Array */ zend_object_value obj; Objektspeicher-Handle und Handler */ } zvalue_value; Boolescher Typ, zval.type=IS_BOOL, Der zval.value.lval Das Feld wird gelesen und der Wert ist 1/0. Wenn es sich um eine Zeichenfolge handelt, liest zval.type=IS_STRING zval.value.str, eine Struktur, die den Zeichenfolgenzeiger und die Länge speichert. Verwenden Sie in der C-Sprache „ Klarschrift
    typedefstruct_zend_rsrc_list_entry {    void *ptr;    int refcount;  }zend_rsrc_list_entry;  🎜>

    Unter diesen ist ptr ein Zeiger auf die endgültige Implementierung der Ressource, beispielsweise ein Dateihandle oder eine Datenbankverbindungsstruktur. Typ ist ein Typ-Tag, der zur Unterscheidung verschiedener Ressourcentypen verwendet wird. refcount wird zur Referenzzählung von Ressourcen verwendet.

    Im Kernel wird der Ressourcentyp über die Funktion ZEND_FETCH_RESOURCE ermittelt.

    [php]-Ansicht Klarschrift

    1. ZEND_FETCH_RESOURCE(con, type, zval *, default, resources_name, resources_type);

    5. Variablentypkonvertierung

    Nach unserem aktuellen Verständnis der PHP-Sprache hängt der Typ der Variable von der Feldangabe zval.type ab Der Inhalt der Variablen lautet wie folgt: zval.type wird in zval.value gespeichert. Wenn in PHP Variablen benötigt werden, sind nur zwei Schritte erforderlich: Ändern Sie den Wert oder Zeiger von zval.value und ändern Sie dann den Typ von zval.type. Für einige der erweiterten PHP-Variablen Array/Object/Resource erfordert die Variablenkonvertierung jedoch mehr Vorgänge.

    Variablenkonvertierungsprinzipien sind in drei Typen unterteilt:

    5.1 Die gegenseitige Konvertierung des Standardtyps

    ist relativ einfach. Befolgen Sie einfach die oben genannten Schritte zur Konvertierung.

    5.2 Konvertierung von Standardtypen und Ressourcentypen

    Der Ressourcentyp kann als int verstanden werden, was für die Konvertierung von Standardtypen praktischer ist. Nach der Umwandlung wird die Ressource geschlossen oder recycelt.

    [php] Ansicht Klarschrift

    1. $var = fopen ('/tmp/aaa.txt', 'a'); // Ressource #1 $var = (int) $var_dump($var); // Ausgabe 1 ?>

    5.3 Standardtypen und Komplexe Typkonvertierung

    Array-Konvertierung in Int/Gleitkomma-Float gibt die Anzahl der Elemente zurück. Bei der Konvertierung in Bool wird zurückgegeben, ob Elemente im Array vorhanden sind. Bei der Konvertierung in einen String wird „Array“ zurückgegeben geworfen.
    Details hängen von der Erfahrung ab, bitte lesen Sie das PHP-Handbuch: http://php.net/manual/en/sprache.types.type-juggling.php

    5.4 Komplexe Typkonvertierung

    Array und Objekt können ineinander umgewandelt werden. Wenn ein Wert eines anderen Typs in ein Objekt konvertiert wird, wird eine Instanz der integrierten Klasse stdClass erstellt.

    Wenn wir PHP-Erweiterungen schreiben, stellt der PHP-Kern eine Reihe von Funktionen für die Typkonvertierung bereit:

    void convert_to_long(zval* pzval)
    void convert_to_double(zval* pzval)
    void convert_to_long_base(zval* pzval, int base)
    void convert_to_null(zval* pzval)
    void convert_to_boolean(zval* pzval)
    void convert_to_array(zval* pzval)
    void convert_to_object(zval* pzval)
    void convert_object_to_type(zval* pzval, convert_func_t converter)

    Der PHP-Kern stellt eine Reihe von Makros für den bequemen Zugriff bereit zval, wird verwendet, um den Wert von zval feinkörniger zu erhalten:

    Zugriffsvariablen(zval).value.str.len Z_ARRVAL_PP(zval_pp)
    Kernel Access Zval Container API
    Makro
    内核访问zval容器的API
    访问变量
    Z_LVAL(zval) (zval).value.lval
    Z_DVAL(zval) (zval).value.dval
    Z_STRVAL(zval) (zval).value.str.val
    Z_STRLEN(zval) (zval).value.str.len
    Z_ARRVAL(zval) (zval). value.ht
    Z_TYPE(zval) (zval).type
    Z_LVAL_P(zval) (*zval).value.lval
    Z_DVAL_P(zval) (*zval).value.dval
    Z_STRVAL_P(zval_p) (*zval).value.str.val
    Z_STRLEN_P(zval_p) (*zval).value.str.len
    Z_ARRVAL_P(zval_p) (*zval). value.ht
    Z_OBJ_HT_P(zval_p) (*zval).value.obj.handlers
    Z_LVAL_PP(zval_pp) (**zval).value.lval
    Z_DVAL_PP(zval_pp) (**zval).value.dval
    Z_STRVAL_PP(zval_pp) (**zval).value.str.val
    Z_STRLEN_PP(zval_pp) (**zval).value.str.len
    Z_ARRVAL_PP(zval_pp) (**zval). value.ht
    Z_LVAL(zval)
    (zval).value.lval
    Z_DVAL(zval) (zval).value.dval
    Z_STRVAL( zval ) (zval).value.str.val
    Z_STRLEN(zval)
    Z_ARRVAL(zval) (zval.ht
    Z_TYPE(zval) (zval).type
    Z_LVAL_P(zval) (*zval).value.lval
    Z_DVAL_P(zval) td > (*zval).value.dval
    Z_STRVAL_P(zval_p) (*zval).value . str.val
    Z_STRLEN_P(zval_p) (*zval).value.str.len
    Z_ARRVAL_P(zval_p) (*zvalvalue.ht
    Z_OBJ_HT_P(zval_p) (*zval).value.obj.handlers
    Z_LVAL_PP(zval_pp) (**zval).value.lval
    Z_DVAL_PP(zval_pp) (**zval ) .value.dval
    Z_STRVAL_PP(zval_pp) (**zval).value.str.val
    Z_STRLEN_PP(zval_pp) (**zval).value.str.len
    (**zval.ht

    6. Variable Symboltabelle und Umfang

    Die Variablensymboltabelle und die Zval-Wertzuordnung von PHP erfolgen über HashTable (Hash-Tabelle, auch Hash-Tabelle genannt, im Folgenden als HT bezeichnet). HashTable wird häufig verwendet in ZE. Sprachfunktionen wie Konstanten, Variablen und Funktionen werden alle von HT organisiert. Der Array-Typ in PHP wird auch über HashTable implementiert.
    Zum Beispiel:

    [php] Ansicht Klarschrift

    1. $var = 'Hallo Welt' ; ?>

    Der Variablenname von $var wird in der Variablensymboltabelle gespeichert und die zval-Struktur repräsentiert den Typ und Wert von $var wird in der Hash-Tabelle gespeichert. Der Kernel implementiert den Zugriff auf PHP-Variablen durch die Hash-Zuordnung der Variablensymboltabelle und der Zval-Adresse.

    Warum müssen wir den Umfang erwähnen? Weil die internen Variablen der Funktion geschützt sind. Je nach Bereich werden PHP-Variablen in globale Variablen und lokale Variablen unterteilt. Jeder Bereich verwaltet PHP eine HashTable mit Symboltabellen. Beim Erstellen einer Funktion oder Klasse in PHP erstellt ZE eine neue Symboltabelle, um anzuzeigen, dass die Variablen in der Funktion oder Klasse lokale Variablen sind. Dadurch wird der Schutz lokaler Variablen erreicht – auf Variablen innerhalb der Funktion kann von außen nicht zugegriffen werden. Beim Erstellen einer PHP-Variablen weist ZE einen zval zu, legt den entsprechenden Typ und Anfangswert fest und fügt die Variable zur Symboltabelle des aktuellen Bereichs hinzu, damit der Benutzer die Variable verwenden kann.
    ZEND_SET_SYMBOL wird im Kernel verwendet, um Variablen festzulegen:

    [php] Ansicht Klarschrift

    1. ZEND_SET_SYMBOL( EG(active_symbol_table), "foo",

    View_zend_executor_globals Struktur

    [php] Ansicht Klarschrift

    1. Zend/zend_globals.h
    2. struct _zend_executor_globals { HashTable symbol_table; //Symboltabelle von global variables HashTable *active_symbol_table; //Symboltabelle lokaler Variablen //Small }; Variable Symboltabelle über das EG-Makro. EG (symbol_table) greift auf die Variablensymboltabelle des globalen Bereichs zu, und EG (active_symbol_table) greift auf die Variablensymboltabelle des aktuellen Bereichs zu. Die lokale Variable speichert einen Zeiger, der bei der Bearbeitung der HashTable an die entsprechende Funktion übergeben wird. Um die Hash-Tabelle und den Umfang der Variablen besser zu verstehen, hier ein einfaches Beispiel:
    3. [php]-Ansicht Klarschrift

    $temp

    =

      'global'
    1. ; } test(); var_dump($temp); 'global' in der HashTable der globalen Symboltabelle. Erstellen Sie die interne Variable $temp des Funktionstests, fügen Sie sie der zum Funktionstest gehörenden Symboltabelle hinzu und weisen Sie den Zeichentyp zval mit dem Wert „aktiv“ zu. 7. Variablenoperationen in PHP-Erweiterungen PHP-Variablen erstellen Wir können die Funktion MAKE_STD_ZVAL (pzv) in der Erweiterung aufrufen, um eine PHP-aufrufbare Variable, MAKE_STD_ZVAL-Anwendung, zu erstellen Eingetroffene Makros sind: [php] view Klarschrift
      1. #define MAKE_STD_ZVAL(zv) ALLOC_ZVAL(zv);INIT_PZVAL(zv) #define ALLOC_ZVAL(z) ZEND _FAST_ALLOC(z, zval, ZVAL_CACHE_LIST) #define ZEND_FAST_ALLOC(p, type, fc_type ) (P) = (type*) emalloc (sizeof (type)) #Define init_pzval (z) (z)-& gt; repcount__gc = 0; >
      2. MAKE_STD_ZVAL(foo) wird erweitert, um die Ansicht

      [php] zu erhalten Klarschrift

        (foo) = (zval *) emalloc(sizeof(zval)); (foo)->refcount__gc = 1 (foo)-> is_ref__gc = 0;
      1. Es ist ersichtlich, dass MAKE_STD_ZVAL drei Dinge tut: Speicher zuweisen, Refcount initialisieren und is_ref in der zval-Struktur. Der Kernel bietet einige Makros, um unsere Vorgänge zu vereinfachen. Sie können den Typ und den Wert von zval in nur einem Schritt festlegen.


        Der dup-Parameter in ZVAL_STRINGL(pzv,str,len,dup)

        Erklären Sie zunächst die Parameter ZVAL_STRINGL(pzv,str,len,dup); str und len zu verstehen, weil wir wissen, dass der Kernel die Adresse der Zeichenfolge und ihre Länge speichert. Die Bedeutung von dup dahinter ist eigentlich sehr einfach. Es zeigt an, ob die Zeichenfolge kopiert werden muss. Wenn der Wert 1 ist, wird zuerst ein neuer Speicher zugewiesen und die Zeichenfolge zugewiesen. Anschließend wird die Adresse des neuen Speichers nach pzv kopiert. Wenn er 0 ist, wird die Adresse von str direkt zval zugewiesen.

        Der Unterschied zwischen ZVAL_STRINGL und ZVAL_STRING

        Wenn Sie den String an einer bestimmten Position abfangen möchten oder die Länge des Strings bereits kennen, können Sie das Makro ZVAL_STRINGL(zval, string, length) verwenden , Duplikat), das die Stringlänge explizit angibt, anstatt strlen() zu verwenden. Dieses Makro verwendet die Stringlänge als Argument. Aber es ist binärsicher und schneller als ZVAL_STRING, da es einen Strlen weniger gibt.
        ZVAL_RESOURCE ist ungefähr gleich ZVAL_LONG

        Wie wir in Kapitel 4 gesagt haben, ist der Wert des Ressourcentyps in PHP eine Ganzzahl, daher funktioniert ZVAL_RESOURCE ähnlich wie ZVAL_LONG, außer dass es den Typ von zval festlegt zu IS_RESOURCE.

        8. Zusammenfassung

        Die schwache Typisierung von PHP wird durch die ZVAL-Containerkonvertierung vervollständigt, und Variablennamen und ZVAL-Daten werden in Hash-Tabellen gespeichert, was einen gewissen Einbußen bei der Betriebseffizienz mit sich bringt. Darüber hinaus kann aufgrund der impliziten Konvertierung von Variablentypen eine unzureichende Erkennung von Variablentypen während des Entwicklungsprozesses zu Problemen führen.

        Die Sprachfunktionen von PHP wie schwache Typisierung, Arrays, Speicherhosting und Erweiterungen eignen sich jedoch sehr gut für Webentwicklungsszenarien. Die Entwicklungseffizienz ist sehr hoch und kann den Produktiterationszyklus beschleunigen. Bei umfangreichen Diensten liegt der Engpass häufig in der Datenzugriffsschicht und nicht in der Sprache selbst. Bei der tatsächlichen Verwendung dient PHP nicht nur als Logikschicht und Präsentationsschicht, wir verwenden sogar den von PHP entwickelten UDPServer/TCPServer als mittlere Daten- und Cacheschicht.

        Das Obige stellt Wang Shuai vor: Ausführlicher PHP-Kern (1) – Erkundung des Prinzips schwach typisierter Variablen, einschließlich verschiedener Aspekte. Ich hoffe, dass es für Freunde hilfreich sein wird, die sich für PHP-Tutorials interessieren.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn