When borrowing implementations from other developers, be sure to check that the code in question has been licensed in such a way as to allow you to reuse the work. Some licenses permit wholesale inclusion of another person's implementation without attribution, while others go so far as to enforce strict limitations on your larger work even though it may only include a small piece of imported code. Read all license documentation carefully, and when in doubt contact the original author for permission.
The PHP Source Tree
Although it should go without saying, the PHP source tree itself is a massive repository of sample code ripe for the picking. Because all of the bundled extensions are thoroughly documented in the PHP online manual, you won't have to guess what the purpose of a given PHP_FUNCTION() block is. If something doesn't make sense, you can be sure that someone watching the PHP mailing lists will be familiar with it and able to explain it to you. Best of all, with the exception of a few bundled libraries and some scattered reproductions, the majority of the PHP source tree is released under the extremely liberal and friendly PHP license.
Within this readily available collection of source files, you'll find detailed examples of nearly every task you'll want to implement. After all, most of the abilities to interact with PHP and extend it exist because one bundled extension or another requires it.
For help working your way through the PHP Source tree, take a look at http://lxr.php.net. This handy tool, regularly regenerated from the sources in CVS, shows PHP's source files with direct, contextual linking to related parts of the source tree. For example, say you're looking at the following code block and wondering what it does:
void *php_hacer_una_thingamajig(int foo, double bar) { return ZEND_GROK_THE_CASBAH(foo + foo * bar); }
You could sort through pages of grep output looking for where ZEND_GROK_THE_CASBAH() was defined, but that can become tedious when you need to trace a definition through a dozen source files. LXR solves this by displaying every macro, function call, constant, or difficult-to-track-down symbol as a hyperlink to the source file and line it was defined on.
Linking Against Third-Party Libraries
As you already saw back in Chapter 17, "Configuring and Linking," extensions such as zlib serve as useful templates for designing config.m4 and config.w32 files that can search for, test, and link against required third-party libraries. This extension, as well as mysql, bcmath, and others, provide excellent examples for exploring optional functionality and enabling a range of variable feature sets depending on the host environment at hand.
Exporting Resources
Chapter 9, "The Resource Data Type," covered the well established API for registering, fetching, and cleaning up resource data types. Because this is the only method, prior to the availability of Zend Engine 2 objects, to store complex internal data structures, you'll find them used in some form or another in many of PHP's bundled extensions.
To begin, consider taking a look at the uncomplicated sockets extension for a reference to using this essential feature. Because this extension shares few API calls with other parts of the PHP Core and links against no external librariesexcept for libc, of courseit provides a relatively simple look at using this otherwise mysterious data type.
Implementing Streams
The stock distribution of PHP includes wrapper implementations for the FTP and HTTP layer 4 protocols, the source code for which can be found in the ext/standard folder in the ftp_fopen_wrapper.c and http_fopen_wrapper.c source files. The php_stream_wrapper structures associated with these are then registered in basic_functions.c, found in the same directory.
The HTTP wrapper implementation provides a thorough yet easy-to-follow demonstration of using context options to modify the behavior of a stream during the open phase. The FTP wrapper, on the other hand, provides a more complete value as a reference thanks to its coverage of all the optional wrapper operations.
Implementing Filters
Included with the base distribution of PHP are a collection of filters found in ext/standard/filters.c. These include the string.* class and the convert.* class. Referring to the string.rot13 filter should give the most easily parsable example of implementing a PHP stream filter.
Also bundled with PHP are the compression filters found in ext/zlib/zlib_filter.c and ext/bz2/bz2_filter.c. The overall structure of these two files is nearly identical, differing primarily in terms of the specific external library function called. Although the work being done is slightly more complex than the aforementioned string.rot13 filter, they may serve as clearer examples as they're presented in isolation: one filter, one source file.
PECL as a Source of Inspiration
Since its inauguration just after the turn of the century, the PHP Extension Code Library, or PECLpronounced "pickle"has grown to house more than 100 extension and SAPI modules that can be optionally built into a PHP installation. These packages include rudimentary extensions, robust API collections, opcode caches, and even modifications to the language syntax itself.
The Traditionalists
The most useful extensions to use as reference during your early stages of development will be the kind that have marked the PHP language since the beginning: the basic glue extension.
In this category, extensions like expect and openal demonstrate simple one-to-one mappings of PHP userspace functions to their library implementations. Here you'll find examples of mapping data types, linking, and general resource management.
PHP5 Object Implementations
The ZE2 object model offers significant advantage over its earlier incarnation; unfortunately, few examples of using this exist in the wild. flitetts offers one such implementation in a fairly small, easy-to-parse package. More robust implementations exist in pdo and other extensions, but these are attached to more complicated application logic. When designing an internal class implementation, it's best to start with the most basic functionality and build from there.
Opcode Caches
Opcode caching has been implemented by a number of projects, and provides performance improvement to websites by saving the compiled opcode form of scripts and only performing recompilation when necessitated by a change in the source script. The opcode cache used by www.php.net, and the one you'll be able to learn from most easily, is APC, the Advanced PHP Cache.
APC hooks into the Zend Engine by replacing the built-in compiler with a caching system that redispatches requests only when the compiled version is not already available in memory. This implementation also makes heavy use of shared memory using its own cross-platform compatible allocation system. It's not a topic to jump into on your first day, but it should eventually provide you with a healthy dose of reliable and reusable ideas.
The Wilder Side
For a look at some topics not covered in this book and unlikely to be found anywhere else, turn to runkit, which exposes the function and class registries and uses the TSRM layer to embed requests within one another. Other unusual examples of manipulating the PHP interpreter include operator, which overrides the meaning of several opcodes, and VLD, the "Vulcan Logic Decoder," which turns compiled scripts into human readable representations. VLD, in particular, allows you to steal a unique look at how the engine ticks, and may serve as its own inspiration for future development down as yet unimagined roads.
The topics covered by these esoteric extensions are well beyond the scope of this book and generally inapplicable to real-world uses, although they demonstrate the extent to which PHP and the Zend Engine allow themselves to be customized to suit thirdparty needs.
PECL as a Design Platform
PECL is not only a source for looking at other people's code. If you're planning to release an extension as an open source project, you could find a much worse home for it than here. Apart from offering a speedy and reliable CVS repository, PECL extensions and SAPI implementations are afforded the opportunity to house their documentation in the official php.net manual. What's more, extensions hosted within PECL that have a valid config.w32 file are automatically built into usable DLLs by the pecl4win build system and made available at http://pecl4win.php.net.
Elsewhere in the PHP CVS Repository
In Chapter 4, "Setting up a Build Environment," you saw instructions for checking out the PHP Source tree from the php-src module at cvs.php.net. Other modules that can be found on this server include pear and pecl, the phpdoc manual and all of its translations, and one projectalmost out of placein the embed repository: php-irssi.
This project was designed to serve as an exemplar for using the embed SAPI introduced in Chapter 19, "Setting up a Host Environment." It demonstrates linking against libphp5.so to provide access to the PHP interpreter from within the popular IRC client irssi. Examples of graceful error handling, output capture and redirection, and simultaneous extending and embedding can be found in this simple and stable stub library.
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