When a serious error occurs, such as a script parse error, PHP will go into bailout mode. In the case of the simple embed examples you've seen so far, that means jumping directly to the PHP_EMBED_END_BLOCK() macro and bypassing any remaining code within the block. Because the purpose of most applications that embed the PHP interpreter is not strictly about executing PHP code, it makes sense to avoid having a PHP script bailout kill the entire application.
One approach might be to confine all executions to very small START/END blocks, so that a given bailout only bails out on the current chuck. The disadvantage to this is that each START/END block functions as its own isolated PHP request. Thus a pair of START/END blocks, as shown here, will not share a common scope, even though the legal syntax of each should allow one block to work with the other:
int main(int argc, char *argv[]) { PHP_EMBED_START_BLOCK(argc, argv) zend_eval_string("$a = 1;", NULL, "Script Block 1"); PHP_EMBED_END_BLOCK() PHP_EMBED_START_BLOCK(argc, argv) /* Will display "NULL", * since variable $a isn't defined in this request */ zend_eval_string("var_dump($a);", NULL, "Script Block 2"); PHP_EMBED_END_BLOCK() return 0; }
Another way to isolate these two zend_eval_string() calls is through the use of some Zend-specific pseudolanguage constructs: zend_try, zend_catch, and zend_end_try. Using these constructs, your application can set up a temporary override for the bailout target and deal with these serious errors in a sane manner. Consider the following variation of the prior example:
int main(int argc, char *argv[]) { PHP_EMBED_START_BLOCK(argc, argv) zend_try { /* Try to execute something that will fail */ zend_eval_string("$1a = 1;", NULL, "Script Block 1a"); } zend_catch { /* There was an error! * Try a different line instead */ zend_eval_string("$a = 1;", NULL, "Script Block 1"); } zend_end_try(); /* Will display "NULL", * since variable $a isn't defined in this request */ zend_eval_string("var_dump($a);", NULL, "Script Block 2"); PHP_EMBED_END_BLOCK() return 0; }
In the second version of this code sample, the parse error that occurs within the zend_try block only bails out as far as the zend_catch block where it's handled by using a good piece of code instead. The same block could be applied to the var_dump() section later on as well; go ahead and try that out for yourself.
Initializing PHP |
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