[I have decided to start adding some entries about the re-factoring of journal home, either it will help someone else or someone will be able to offer some comments] I am busy doing a lot of changes to the code of Journalhome.com to ensure that it runs better than the current software, (that is no longer supported in any case). My aim is to speed up the whole delivery of the page to the browsers. Some of the tools used to speed up the delivery of pages is compression with things like ob_gzhander and ob_start The problem with that is that some code that I want to be executed at the very end of the script, (as the script is completing) it does not seem to be executed. In php when you call ob_start('ob_gzhandler'); it tells the php compiler to take all the output, (everything going to the screen), and, instead of sending it to the screen we will send the string to a function called ob_gzhandler who in turn will return a compressed string. Normally the way it works is: Code =//=> PHP compiler=//=> Send to the browser (as soon as code want it to go, we cannot get it back) =//=> Do do some completion code With ob_start( ... ) it is a litte bit more complex Code =//=> ob_start( ... ) PHP compiler=//=> ob_end_flush(...) =//=> Send to the browser, (all at once) =//=> Do do some completion code What this means is that the created page is sent out as one big string to the browser. In practice, a page is almost always sent as one big chunk of string, but we cannot really control the string that is sent out. So we can call a function to 'handle' the string and do what we want with it. Code =//=> ob_start( 'ob_gzhandler' ) PHP compiler=//=> ob_end_flush(...) =//=> ob_gzhandler( $str ) { // compress it } =//=> Send that to the browser, (all at once) =//=> Do do some completion code The problem with that is the function ob_gzhandler(...) does not seem to allow the "Do do some completion code"
The problem is almost certainly with register_shutdown_function(...), because as the manual clearly says, if any of the registered function call exit() then the processing will stop completely and no other registered function will be called. So I can only guess that ob_gzhandler(...) itself registers a function that calls exit(), (of course this is only a guess). The other bigger problem with that logic, (and kind of backs up my theory), is that it seems to allow _some_of the registered code to be completed. This makes sense as the shutdown functions are called in the order they are registered so the ones registered before ob_start('ob_gzhandler'); will be executed but not the ones after. For example... <?php function foo() { echo "This should be called last"; }
ob_start('ob_gzhandler'); // replace with ob_start(); for it to work register_shutdown_function('foo'); echo "This is called now<br />"; ?> This works as expected with PHP 5.x and later, but not with php 4.x, (well not with php 4.4.x that I am using). <?php function foo1() { echo "This should be called second to last<br />"; } function foo() { echo "This should be called last<br />"; } register_shutdown_function('foo1'); ob_start('ob_gzhandler'); // replace with ob_start(); for it to work register_shutdown_function('foo'); echo "This is called now<br />"; ?> This will also not work with all flavours of php4.x but it will work with php5.x As I am planning to move to php 5 this is not a problem but I am trying very hard to make sure that he new code works on both 4.x and 5.x, (simply because I want the code to be open source. The 'fix' I have is to remove the compression altogether with php < 5.x <?php
function foo()
{
echo "This should be called last";
}
if( phpversion() < 5.00 ) { ob_start();
} else { ob_start('ob_gzhandler');}
register_shutdown_function('foo');
echo "This is called now<br />";
?>
Obviously this is not a perfect solution as the code is no longer compressed, but for those that will be using php4, (that is no longer supported btw), then it will have to do. |