Wang Shuai: go deep into the PHP kernel (I)-exploring the principle of weak type variables

Source: Internet
Author: User
: This article mainly introduces Wang Shuai: go deep into the PHP kernel (1)-exploring the principle of weak type variables. if you are interested in PHP tutorials, refer to it. PHP is a simple and powerful language that provides many language features applicable to the Web, including weak variable types. under the weak type mechanism, you can assign any type of value to a variable.
PHP is executed through Zend Engine (ZE). ZE is written in C and implements a weak type mechanism at the underlying layer. ZE memory management uses optimization policies such as copy at write time and reference count to reduce the memory copy during variable assignment.

The following describes how to operate PHP variables from the perspective of PHP extension.

1. PHP variable type

PHP has eight types of variables:

  • Standard type: Boolean boolen, integer, floating point float, string
  • Complex type: array, object
  • Special type: resource

PHP does not strictly check the variable type. variables can declare their types without displaying them, but assign values directly during running. You can also convert the variable type freely. In the following example, $ I can assign any type of value without implementation declaration.

[Php] view plaincopy

If you do not have a deep understanding of the weak type principle, you will be pleasantly surprised when comparing variables.

[Php] view plaincopy

All the above three results are equal, because variable conversion is performed in PHP during variable comparison. If you want to determine the value and type at the same time, use three = (for example, $ a = 0. Maybe you will think it is common, maybe you will think it is amazing, so please go deep into the PHP kernel with me and explore the principles of PHP variables.

2. Introduction to variable storage and standard types

All PHP variables are implemented using the zval struct. we can see the definition of zval in Zend/zend. h:

[Php] view plaincopy

  1. Typedef union _ zvalue_value {long lval;/* long value */double dval;/* double value */struct {char * val; int len; /* this will always be set for strings */} str;/* string (always has length) */HashTable * ht;/* an array */zend_object_value obj; /* stores an object store handle, and handlers */} zvalue_value;

Attribute name Description Default value
Refcount _ gc Reference count 1
Is_ref _ gc Indicates whether it is a reference. 0
Value Store variable values
Type Variable type

Refcount _ gc and is_ref _ gc indicate whether the variable is a reference. The type field identifies the type of the variable. The value of type can be IS_NULL, IS_BOOL, IS_LONG, IS_FLOAT, IS_STRING, IS_ARRAY, IS_OBJECT, and IS_RESOURCE. PHP selects how to store zvalue_value based on the type.
Zvalue_value can realize the core of weak variable types, which are defined as follows:

[Php] view plaincopy

  1. Typedef union _ zvalue_value {long lval;/* long value */double dval;/* double value */struct {char * val; int len; /* this will always be set for strings */} str;/* string (always has length) */HashTable * ht;/* an array */zend_object_value obj; /* stores an object store handle, and handlers */} zvalue_value;

Boolean, zval. type = IS_BOOL. the zval. value. lval field is read and the value is 1/0. If it is a string, zval. type = IS_STRING, it will read zval. value. str, which is a struct and stores the string pointer and length.

In C, "\ 0" is used as the string terminator. That is to say, if a string "Hello \ 0 World" is output in C language using printf, it can only output hello, because "\ 0" will think that the character has ended. In PHP, the _ zval_value.str.len of The struct is used to control the length of the string. related functions will not end with "\ 0. Therefore, PHP strings are binary safe.

If it is NULL, you only need zval. type = IS_NULL and do not need to read the value.

Through zval encapsulation, PHP implements weak types. For ZE, zval can be used to access any types.

3. Array and Object Array of the advanced type

An array is a very powerful data structure in PHP. it can be divided into an index array and an associated array. zval. type = IS_ARRAY. Each key in the associated array can store any type of data. PHP arrays are implemented using Hash tables. the values of the arrays are stored in zval. value. ht.

The implementation of PHP hash tables will be discussed later.

Zval. type = IS_OBJECT of the object type. The value exists in zval. value. obj.

4. Introduction to special types -- Resource

The resource type is a special type, zval. type = IS_RESOURCE, which has some data structures that are difficult to describe with common types in PHP, such as file handle. it is a pointer for C language, but PHP does not have the pointer concept, it cannot be constrained by conventional types. Therefore, PHP uses the resource type concept to encapsulate variables similar to file pointers in C language in the zval structure. The resource type value is an integer. ZE obtains the value from the resource hash table.

Definition of resource type:

[Php] view plaincopy

  1. Typedefstruct_zend_rsrc_list_entry {void * ptr; int type; int refcount;} zend_rsrc_list_entry;

Ptr is a pointer to the final implementation of the resource, such as a file handle or a database connection structure. Type is a type tag used to distinguish different resource types. Refcount indicates the reference count of a resource.

In the kernel, the resource type is obtained through the ZEND_FETCH_RESOURCE function.

[Php] view plaincopy

  1. ZEND_FETCH_RESOURCE (con, type, zval *, default, resource_name, resource_type );

5. variable type conversion

According to our understanding of the PHP language, the type of the variable depends on the zval. type field, and the content of the variable is stored in zval. value according to zval. type. When a variable is required in PHP, only two steps are required: change the value or pointer of zval. value, and then change the type of zval. type. However, for some PHP advanced variables Array/Object/Resource, variable conversion requires more operations.

There are three types of variable conversion principles:

5.1 Standard type conversion

It is relatively simple, just follow the steps above to convert.

5.2 Conversion of standard and resource types

The resource type can be understood as int, which facilitates the conversion of standard types. After conversion, the resource will be closed or recycled.

[Php] view plaincopy

5.3 Standard type and complex type conversion

If the Array is converted to an int or float type, the number of elements is returned. if The bool is converted to an Array, the system returns whether there are elements in the Array. If the Array is converted to a string, the system returns 'array' and throws a warning.
Detailed content depends on experience, please read the PHP Manual:

5.4 complex type conversion

Array and object can be converted. If any other type of value is converted to an object, a built-in class is created.StdClass.

When writing PHP extensions, the PHP kernel provides a set of functions for type conversion:

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)

The PHP kernel provides a set of macros to easily access zval, which is used to obtain zval values in a finer granularity:

The kernel accesses the zval container API
Macro Access variable
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

6. symbol table and scope of variables

The ing between the variable symbol table of PHP and the zval value is through HashTable (hash table, also called hash table, HT). HashTable is widely used in ZE, language features such as constants, variables, and functions are all organized by HT. the array type in PHP is also implemented by HashTable.
For example:

[Php] view plaincopy

$ Var variable names are stored in the variable symbol table, and the zval structure representing the $ var type and value is stored in the hash table. The kernel uses the hash ing between the variable symbol table and the zval address to access PHP variables.

Why do we need to raise the scope? This is because of variable protection in the function. PHP variables in the scope are divided into global variables and local variables. Each scope of PHP maintains a HashTable symbol table. When you create a function or class in PHP, ZE creates a new symbol table, indicating that the variable in the function or class is a local variable, in this way, local variables are protected-external variables cannot be accessed within the function. When you create a PHP variable, ZE assigns a zval, sets the corresponding type and initial value, and adds the variable to the symbol table in the current scope so that you can use the variable.
Use ZEND_SET_SYMBOL in the kernel to set the variable:

[Php] view plaincopy

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

View the _ zend_executor_globals structure

[Php] view plaincopy

  1. Zend/zend_globals.h
  2. Struct _ zend_executor_globals {// slightly HashTable symbol_table; // symbol table of global variables HashTable * active_symbol_table; // symbol table of local variables // omitted };

When writing PHP extensions, you can use the EG macro to access the variable symbol table of PHP. EG (symbol_table) accesses the variable symbol table in the global scope, EG (active_symbol_table) accesses the variable symbol table in the current scope, and partial variables store pointers, it is passed to the corresponding function when performing operations on HashTable.

To better understand the hash table and scope of variables, a simple example is given:

[Php] view plaincopy

Create the variable $ temp outside the function and add it to the global symbol table. at the same time, assign a character type zval in the HashTable of the global symbol table with the value 'global '. Create the variable $ temp in the test function and add it to the symbol table belonging to the test function. assign the variable type zval with the value 'activity '.

7. variable operations in PHP extension

Create PHP variables

We can call the MAKE_STD_ZVAL (pzv) function in the extension to create a PHP callable variable. The Macros applied by MAKE_STD_ZVAL include:

[Php] view plaincopy

  1. # Define MAKE_STD_ZVAL (zv) ALLOC_ZVAL (zv); INIT_PZVAL (zv) # define ALLOC_ZVAL (z) values (z, zval, values) # define ZEND_FAST_ALLOC (p, type, fc_type) (p) = (type *) emalloc (sizeof (type) # define INIT_PZVAL (z)-> refcount _ gc = 1; (z) -> is_ref _ gc = 0;


[Php] view plaincopy

  1. (Foo) = (zval *) emalloc (sizeof (zval); (foo)-> refcount _ gc = 1; (foo)-> is_ref _ gc = 0;

As you can see, MAKE_STD_ZVAL does three things: allocating memory, initializing refcount and is_ref in the zval structure.

The kernel provides some macros to simplify our operations. you can set the zval type and value in only one step.

API Macros for Accessing zval
Macro Implementation method
ZVAL_NULL (pvz) Z_TYPE_P (pzv) = IS_NULL
ZVAL_BOOL (pvz) Z_TYPE_P (pzv) = IS_BOOL;
Z_BVAL_P (pzv) = B? 1: 0;
ZVAL_TRUE (pvz) ZVAL_BOOL (pzv, 1 );
ZVAL_FALSE (pvz) ZVAL_BOOL (pzv, 0 );
ZVAL_LONG (pvz, l) (l is the value) Z_TYPE_P (pzv) = IS_LONG; Z_LVAL_P (pzv) = l;
ZVAL_DOUBLE (pvz, d) Z_TYPE_P (pzv) = IS_DOUBLE; Z_LVAL_P (pzv) = d;
ZVAL_STRINGL (pvz, str, len, dup) Z_TYPE_P (pzv) = IS_STRING; Z_STRLEN_P (pzv) = len;
If (dup ){
{Z_STRVAL_P (pzv) = estrndup (str, len + 1 );}
} Else {
{Z_STRVAL_P (pzv) = str ;}
ZVAL_STRING (pvz, str, len) ZVAL_STRINGL (pzv, str, strlen (str), dup );
ZVAL_RESOURCE (pvz, res) Z_TYPE_P (pzv) = IS_RESOURCE; Z_RESVAL_P (pzv) = res;

Dup parameter in ZVAL_STRINGL (pzv, str, len, dup)

Describe the ZVAL_STRINGL (pzv, str, len, dup); str and len parameters, because we know that the kernel stores the string address and its length, the meaning of the following dup is actually very simple. it specifies whether the string needs to be copied. If the value is 1, a new memory is applied for and the string is assigned. then, the address of the new memory is copied to pzv. if the value is 0, the str address is directly assigned to zval.

Differences between ZVAL_STRINGL and ZVAL_STRING

If you want to intercept the string at a certain position or you already know the length of the string, you can use the macro ZVAL_STRINGL (zval, string, length, duplicate ), it explicitly specifies the string length, instead of strlen (). This macro uses the string length as a parameter. However, it is binary secure and faster than ZVAL_STRING because strlen is missing.

As we mentioned in chapter 4, the value of the resource type in PHP is an integer, so ZVAL_RESOURCE and ZVAL_LONG work almost, but it sets the zval type to IS_RESOURCE.

8. Summary

The weak type of PHP is converted by zval container of ZE. the variable name and zval data are stored in the hash table, which is at a certain cost in terms of running efficiency. In addition, due to implicit conversion of variable types, insufficient variable types are detected during development, which may cause problems.

However, the language features of PHP, such as weak types, arrays, memory hosting, and extensions, are very suitable for Web development scenarios. The development efficiency is very high and the product iteration cycle can be accelerated. In massive Services, the bottleneck usually exists at the data access layer, rather than the language itself. In practice, PHP serves not only the logic layer and presentation layer, but also the UDPServer/TCPServer developed by PHP as the middle layer of data and cache.

The above introduces Wang Shuai: go deep into the PHP kernel (1)-exploring the principle of weak type variables, including some content, and hope to help those who are interested in PHP tutorials.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.