At various stages of the PHP lifecycle, some service-related operations are implemented through the SAPI interface. These built-in implementations of the physical location in the PHP source SAPI directory. This directory contains PHP code for each server abstraction layer, such as command-line program implementation, Apache mod_php module implementation and FASTCGI implementation, and so on.
The same conventions are observed between each server abstraction layer, which we call the SAPI interface. Each SAPI implementation is a _sapi_module_struct struct variable. (SAPI interface). In the source code of PHP, when the need to invoke server-related information, all through the SAPI interface corresponding method call implementation, and this corresponding method in each server abstraction layer implementation will have their own implementation.
Here is the simple for SAPI:
For example, in CGI mode and APACHE2 server, they start with the following methods:
Cgi_sapi_module.startup (&cgi_sapi_module) // CGI mode cgi/cgi_main.c file Apache2_sapi_module.startup ( &apache2_sapi_module); apache2 Server apache2handler/sapi_apache2.c file
The cgi_sapi_module here is a static variable of the SAPI_MODULE_STRUCT structure. Its startup method points to the Php_cgi_startup function pointer. In this struct, there are many other methods or fields in addition to the startup function pointer. Some of the definitions are as follows:
struct _sapi_module_struct {char *name; Name (identification with) char *pretty_name; A better understanding of the name (self-translated) int (*startup) (struct _sapi_module_struct *sapi_module); Start function int (*shutdown) (struct _sapi_module_struct *sapi_module); Close method Int (*activate) (tsrmls_d); activate int (*deactivate) (tsrmls_d); Deactivate int (*ub_write) (const char *STR, unsigned int str_length tsrmls_dc); Write operation not cached (unbuffered write) void (*flush) (void *server_context); Flush struct Stat * (*get_stat) (tsrmls_d); Get UID char * (*getenv) (char *name, size_t name_len tsrmls_dc); getenv void (*sapi_error) (int type, const char *error_msg, ...); /* ERROR handler */INT (*header_handler) (Sapi_header_struct *sapi_header, Sapi_header_op_enum op, sapi_headers _struct *sapi_headers tsrmls_dc); /* Header Handler *//* Send headers handler */INT (*send_headers) (sapi_headers_struct *sapi_headers tsrmls_dc); void (*send_header) (Sapi_header_struCT *sapi_header, void *server_context tsrmls_dc); /* Send Header handler */INT (*read_post) (char *buffer, uint count_bytes tsrmls_dc); /* Read POST Data */char * (*read_cookies) (tsrmls_d); /* Read Cookies */* Register server variables */void (*register_server_variables) (Zval *track_vars_array Tsrmls_ DC); void (*log_message) (char *message); /* LOG message */time_t (*get_request_time) (tsrmls_d); /* Request time */void (*terminate_process) (tsrmls_d); /* Child Terminate */char *php_ini_path_override; Covered ini path ...};
These structures are defined in the interface implementations of each server. As defined by Apache2:
Static Sapi_module_struct Apache2_sapi_module = { "Apache2handler", "Apache 2.0 Handler", php_apache2_ startup,/ * startup */ Php_module_shutdown_wrapper,/ * shutdown */ ...}
At present, many of the SAPI implementations built into PHP are no longer maintained or become a bit of a non-mainstream, and the PHP community is currently considering moving some SAPI out of the code base. The Community's consideration of many features is that unless it is really necessary, or some functionality is nearly universal, it is in the PECL library, such as the very popular APC cache extension that goes into the core code base.
The entire SAPI is similar to an application in object-oriented template method patterns. Some of the functions contained in the SAPI.C and SAPI.h files are abstract templates in template method patterns, and each server's definition of Sapi_module and related implementations is a specific template.
Such a structure is used in PHP's source code, for example, in PHP extension development, each extension needs to define a zend_module_entry structure. The function of this structure is similar to that of sapi_module_struct structure, and it is an application of similar template method pattern. In the life cycle of PHP, if you need to invoke an extension, the method it calls is the method specified in the Zend_module_entry struct, as mentioned in the previous section, when the request initialization for each extension is performed, the Request_startup_func method is called uniformly. In the definition of each extension, the request_startup_func corresponding function is specified by the macro php_rinit. Take the VLD extension as an example: its request is initialized to Php_rinit (VLD), which corresponds to the implementation of this function in the extension:
Php_rinit_function (VLD) {}
Therefore, we also need to implement these interfaces when we write the extension, and we also need to implement the corresponding SAPI when implementing each server interface.
8.PHP kernel exploration: Explore SAPI again