Note: Prior to working through the rest of this chapter, you should retrieve clean, unmodified source trees of your favorite Web server. We're working with Apache (available at http://www.apache.org/) and, of course, with PHP (available at http://www.php.net/ - does it need to be said?).
Make sure that you can compile a working PHP environment by yourself! We won't go into this issue here, however, as you should already have this most basic ability when studying this chapter.
Before we start discussing code issues, you should familiarize yourself with the source tree to be able to quickly navigate through PHP's files. This is a must-have ability to implement and debug extensions.
The following table describes the contents of the major directories.
|php-src||Main PHP source files and main header files; here you'll find all of PHP's API definitions, macros, etc. (important). Everything else is below this directory.|
|php-src/ext||Repository for dynamic and built-in modules; by default, these are the "official" PHP modules that have been integrated into the main source tree. From PHP 4.0, it's possible to compile these standard extensions as dynamic loadable modules (at least, those that support it).|
|php-src/main||This directory contains the main php macros and definitions. (important)|
|php-src/pear||Directory for the PHP Extension and Application Repository. This directory contains core PEAR files.|
|php-src/sapi||Contains the code for the different server abstraction layers.|
|TSRM||Location of the "Thread Safe Resource Manager" (TSRM) for Zend and PHP.|
|ZendEngine2||Location of the Zend Engine files; here you'll find all of Zend's API definitions, macros, etc. (important).|
Discussing all the files included in the PHP package is beyond the scope of this chapter. However, you should take a close look at the following files:
php-src/main/php.h, located in the main PHP directory. This file contains most of PHP's macro and API definitions.
php-src/Zend/zend.h, located in the main Zend directory. This file contains most of Zend's macros and definitions.
php-src/Zend/zend_API.h, also located in the Zend directory, which defines Zend's API.
Zend is built using certain conventions; to avoid breaking its standards, you should follow the rules described in the following sections.
For almost every important task, Zend ships predefined macros that are extremely handy. The tables and figures in the following sections describe most of the basic functions, structures, and macros. The macro definitions can be found mainly in zend.h and zend_API.h. We suggest that you take a close look at these files after having studied this chapter. (Although you can go ahead and read them now, not everything will make sense to you yet.)
Resource management is a crucial issue, especially in server software. One of the most valuable resources is memory, and memory management should be handled with extreme care. Memory management has been partially abstracted in Zend, and you should stick to this abstraction for obvious reasons: Due to the abstraction, Zend gets full control over all memory allocations. Zend is able to determine whether a block is in use, automatically freeing unused blocks and blocks with lost references, and thus prevent memory leaks. The functions to be used are described in the following table:
|emalloc()||Serves as replacement for malloc().|
|efree()||Serves as replacement for free().|
|estrdup()||Serves as replacement for strdup().|
|estrndup()||Serves as replacement for strndup(). Faster than estrdup() and binary-safe. This is the recommended function to use if you know the string length prior to duplicating it.|
|ecalloc()||Serves as replacement for calloc().|
|erealloc()||Serves as replacement for realloc().|
To allocate resident memory that survives termination of the current script, you can use malloc() and free(). This should only be done with extreme care, however, and only in conjunction with demands of the Zend API; otherwise, you risk memory leaks.
The following directory and file functions should be used in Zend modules. They behave exactly like their C counterparts, but provide virtual working directory support on the thread level.
Strings are handled a bit differently by the Zend engine than other values such as integers, Booleans, etc., which don't require additional memory allocation for storing their values. If you want to return a string from a function, introduce a new string variable to the symbol table, or do something similar, you have to make sure that the memory the string will be occupying has previously been allocated, using the aforementioned e*() functions for allocation. (This might not make much sense to you yet; just keep it somewhere in your head for now - we'll get back to it shortly.)
Complex types such as arrays and objects require different treatment. Zend features a single API for these types - they're stored using hash tables.
Note: To reduce complexity in the following source examples, we're only working with simple types such as integers at first. A discussion about creating more advanced types follows later in this chapter.