As of PHP 5.1, interdependencies between extensions can be enforced. Because extensions can be either built statically into PHP or loaded dynamically as shared objects, it's necessary to enforce the dependencies in two locations.
Configuretime Module Dependency
The first location is within the config.m4 file you've been looking so closely at during the course of this chapter. Here, you'll use the PHP_ADD_EXTENSION_DEP(extname, depname[,optional]) macro to indicate that the extname extension depends on the depname extension. When extname is built statically into PHP, the ./configure script will use this line to determine that depname must be initialized first. The optional parameter is a flag to indicate that depname should be loaded before extname if its also being built statically, but that it's not a required dependency.
An example of this macro in use can be found in PDO driverssuch as pdo_mysqlwhich are predictably dependent on the PDO extension:
ifdef([PHP_ADD_EXTENDION_DEP], [ PHP_ADD_EXTENSION_DEP(pdo_mysql, pdo) ])
Notice that the PHP_ADD_EXTENSION_DEP() macro was wrapped in an ifdef() construct. This is because PDO and its drivers are meant to compile on any version of PHP greater than or equal to 5.0, yet the PHP_ADD_EXTENSION_DEP() macro does not exist until version 5.1.0.
Runtime Module Dependency
The next location where you'll need to register dependencies is within the zend_module_entry structure itself. Consider the zend_module_entry structure you declared in Chapter 5:
zend_module_entry sample_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_SAMPLE_EXTNAME, php_sample_functions, NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_SAMPLE_EXTVER, #endif STANDARD_MODULE_PROPERTIES };
Adding runtime module dependency information means making a minor change to the STANDARD_MODULE_HEADER section.
zend_module_entry sample_module_entry = { #if ZEND_MODULE_API_NO >= 220050617 STANDARD_MODULE_HEADER_EX, NULL, php_sample_deps, #elif ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_SAMPLE_EXTNAME, php_sample_functions, NULL, /* MINIT */ NULL, /* MSHUTDOWN */ NULL, /* RINIT */ NULL, /* RSHUTDOWN */ NULL, /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_SAMPLE_EXTVER, #endif STANDARD_MODULE_PROPERTIES };
Now, if the ZEND_MODULE_API_NO is high enoughindicating one of the beta releases of PHP 5.1.0 or laterSTANDARD_MODULE_PROPERTIES will be replaced with a slightly more complex structure containing a reference to module dependency information.
This target structure would then be defined above your zend_module_entry struct as something like the following:
#if ZEND_MODULE_API_NO >= 220050617 static zend_module_dep php_sample_deps[] = { ZEND_MODULE_REQUIRED("zlib") {NULL,NULL,NULL} }; #endif
Just like a zend_function_entry vector, this list can take as many entries as necessary checking each dependency in order. If an attempt is made to load a module with an unmet dependency, Zend will abort the load reporting the name of the unmet dependency so that the end user can resolve it by loading the other module first.
The PHP Life Cycle
Variables from the Inside Out
Memory Management
Setting Up a Build Environment
Your First Extension
Returning Values
Accepting Parameters
Working with Arrays and HashTables
The Resource Data Type
PHP4 Objects
PHP5 Objects
Startup, Shutdown, and a Few Points in Between
INI Settings
Accessing Streams
Implementing Streams
Diverting the Stream
Configuration and Linking
Extension Generators
Setting Up a Host Environment
Advanced Embedding
Appendix A. A Zend API Reference
Appendix B. PHPAPI
Appendix C. Extending and Embedding Cookbook
Appendix D. Additional Resources