...so apparently iBuildings fired up a new techportal, with editor-in-chief as Cal Evans. Cal recently moved to The Netherlands to join iBuildings, before as we know he was doing the Zend podcasts from the US. (What happened with the podcasts anyway? I loved to listen them while going to work.)
The techPortal already has some nice articles, like debugging development and getting started with phpUnderControl, and it also promotes the 2009 WinPHP Challenge. (XBox, anyone?)
In the meantime PHP TestFest is also getting a kick-off, main goal of which is to improve PHP test coverage and to bring together the PHP user groups.
So, there is a lot of happening going around with PHP, keep your eyes open folks!
Showing posts with label php. Show all posts
Showing posts with label php. Show all posts
2009-04-04
2008-07-28
The slow echo
...so i was about to profile a web application written in php, and as all of us does when doing so, i scattered the code around echoing microtime differences. (Ok, ok, some of you might use log instead.)
To my greatest surprise the part where the application showed significant slowdown in some cases, was a simple echo statement. Well, i wont be able to optimize that, will i? Why can this be happening?
After a bit of googling, i came across this site, where they suggest to split up the echo to smaller chunks to avoid network fragmentation. Hmm, i gave it a try, but no difference. It is a rather old post so i was scrolling down on the comments (most of them are engaging into the question of determining MTU and completely miss the point) to see if people still face this problem, and what are their solutions. The very last post (at that time) suggested simply using output buffering.
Well, my application was already using ob, but as i inspected the code more closely, one of the modules that was included early in the page generation, simply switched ob off!
Damm, switching it back speeded up the application again!
So what is happening in the background?
I am not sure about the implementation of echo, but i guess when echoing a large string over a slow network, if output buffering is not used, echo waits until it has sent the last byte. In other words the network latency comes down to php level.
However, if you use output buffering, you can generate the whole page quickly, then have the webserver send it to the client over the network, all the latency is offloaded from php and will not reflect in the execution time.
To sum up, output buffering is your true friend.
To my greatest surprise the part where the application showed significant slowdown in some cases, was a simple echo statement. Well, i wont be able to optimize that, will i? Why can this be happening?
After a bit of googling, i came across this site, where they suggest to split up the echo to smaller chunks to avoid network fragmentation. Hmm, i gave it a try, but no difference. It is a rather old post so i was scrolling down on the comments (most of them are engaging into the question of determining MTU and completely miss the point) to see if people still face this problem, and what are their solutions. The very last post (at that time) suggested simply using output buffering.
Well, my application was already using ob, but as i inspected the code more closely, one of the modules that was included early in the page generation, simply switched ob off!
Damm, switching it back speeded up the application again!
So what is happening in the background?
I am not sure about the implementation of echo, but i guess when echoing a large string over a slow network, if output buffering is not used, echo waits until it has sent the last byte. In other words the network latency comes down to php level.
However, if you use output buffering, you can generate the whole page quickly, then have the webserver send it to the client over the network, all the latency is offloaded from php and will not reflect in the execution time.
To sum up, output buffering is your true friend.
2008-07-02
PHP RSS parsers
...so the other day i figured out that the parser i used so far (LastRss) was not able to read Atom feeds. Since our beloved Blogger only publishes atom feeds i needed to find a cure for the problem.
One easy solution is to ask FeedBurner to convert between rss and atom, which works pretty well, but better not mess with the Gods, lets do it the proper way.
Then i came across this blog entry, that compared some of the existing solutions. Finally i chose SimplePie, which works brilliantly ever since. To have an overview of the solutions, here is my little comparison:
LastRss
+ simple
+ fast
+ small footprint
- no support for Atom
- website looks interesting recently (says: It works!)
Zend_Feed
+ part of Zend Framework
+ supports Rss and Atom
+ well documented
- supports PHP5 only
Magpie
+ supports Rss and Atom ("with few exceptions" :))
+ long time out there
- long time out there :) seems like it has never really grown up
SimplePie
+ seems like it supports everything
+ well documented
+ fresh and stable project
- one heavy includefile if it bothers you (350K)
XML_RSS (Pear)
- i am not sure, but i think only supports Rss feeds
- Pear dependencies
- "Oldest open bug: 326 days"
RSS_PHP
- supports Rss only
- PHP 5 only (i know, i know, we should all live in a PHP5 world, but we dont)
- "A commercial version (v3) of the RSS Parser / XML Parser for PHP [rss_php] is now released and available for download. This release fixes a couple of tiny bugs and adds far more functionality...Our original version (RSS_PHP v1) is still freely available." - so you can get a buggy version for free, the commercial version costs 15USD.
One easy solution is to ask FeedBurner to convert between rss and atom, which works pretty well, but better not mess with the Gods, lets do it the proper way.
Then i came across this blog entry, that compared some of the existing solutions. Finally i chose SimplePie, which works brilliantly ever since. To have an overview of the solutions, here is my little comparison:
LastRss
+ simple
+ fast
+ small footprint
- no support for Atom
- website looks interesting recently (says: It works!)
Zend_Feed
+ part of Zend Framework
+ supports Rss and Atom
+ well documented
- supports PHP5 only
Magpie
+ supports Rss and Atom ("with few exceptions" :))
+ long time out there
- long time out there :) seems like it has never really grown up
SimplePie
+ seems like it supports everything
+ well documented
+ fresh and stable project
- one heavy includefile if it bothers you (350K)
XML_RSS (Pear)
- i am not sure, but i think only supports Rss feeds
- Pear dependencies
- "Oldest open bug: 326 days"
RSS_PHP
- supports Rss only
- PHP 5 only (i know, i know, we should all live in a PHP5 world, but we dont)
- "A commercial version (v3) of the RSS Parser / XML Parser for PHP [rss_php] is now released and available for download. This release fixes a couple of tiny bugs and adds far more functionality...Our original version (RSS_PHP v1) is still freely available." - so you can get a buggy version for free, the commercial version costs 15USD.
2008-05-07
PHP Certification Study Guide Errors
If you have been already preparing for Zend PHP5 Certification exam from the official study guide, you know it has many annoying errors and misleading statements. Up until the beginning of April there was no forum/listing where you could cross-check the errors, but now we have this errata in our hands. Its pretty complete, i only missed two thing that i noticed myself while i was studying. I added these in the comments section of the page. For the sake of completeness i repeat the list hereby. Happy studying!
First Edition Errata
Page 7:
reads "If you need to output data through a function, you can use print() instead". Person reporting comments that "PHP manual makes it clear that print is not really a function but rather a language construct" So perhaps we just need to change the wording.
Page 11:
reads "When converted to a number or a STRING, a boolean becomes ... 0 otherwise". Compare this to
http://www.php.net/manual/en/language.types.string.php
saying:
Boolean FALSE is converted to "" (the empty string).
Page 12:
top line reads "...want to convert to enclosed in brackets"... this should read "want to convert to enclosed in parentheses"
Page 17:
should read $a = int('Test'); //$a==0 ... echo ++$a; //outputs 1. Otherwise the output will read "Tesu" because of the incrementing
Page 19:
lines 2,3: If both bits are either set or unset, the resulting bit is unset
Page 26:
check versus table in the manual http://www.php.net/manual/en/language.operators.php
Page 29:
on while loops: should say "they allow you to perform a series of operations until a condition evaluates to false"
Page 34:
the line "if($oldErrorHandler) will cause an error... need to put global $oldErrorHandler at the beginning of function myErrorHandler(). Also change to $oldErrorHandler = set_error_handler('myErrorHandler');
Page 50:
should read "giving the key for the specific element..."
Page 52:
-- if the two arrays had common elements that also share the same string keys or that have numeric keys (even if they are different) they would only appear once in the end result. This isn't true and should be changed to "if the two arrays had common keys (either string or numeric) they would only appear once in the end result"
Page 53:
var_dump ($a==$c); //should be false
Page 54:
should be echo array_key_exists('a', $a);
Page 54:
should be echo in_array (2, $a);
Page 55:
typo - "note how key key association..."
Pages 56-57: use of reset() is misleading here: only if the $array is passed by-reference to the function, it would be necessary to be reset; otherwise we'll find a brand new reset array inside the function by default.
Page 57:
should be $array = array(1,2,3); ... end ($array); to work with code right after it
Page 67:
"Push and pull" should be "push and pop"
Page 68:
should read "if you intend to use an array as a queue, you can add elements to the beginning and extract them from the end by using the array_unshift() and array_pop() functions".. Also should change the code appropriately
Page 76:
"Here's an escaped backslash - \ - "... should read "...backslash -\\"
Page 77:
echo srtr('abc','a','1'); //(instead of strstr)
Page 79:
strncasecamp instead of strcasencmp
Page 81:
Line 1 should be - "You can use the strspn() function..."
Page 87:
should read "A sign specifier (a plus or minus symbol) ... "
Page 88:
printf("%d", $f); //prints 123
Page 92:
should read "the function returns integer 1 if the match is successful"
Page 98:
should read "Contrary to popular belief, POST is not an inherently more secure way to ..."
Page 99:
2nd par, should read "As you can see, the data has been encoded and appended to the end of "...
Page 99:
should be [direction] not [dir]
Page 99:
Under the [FORM submitted with POST] section, the code says <input type="password" name = "pass' - note the single quote at the end of pass
Page 107:
$data should be $date
Page 109:
Check the "setcookie delete" description
Page 122:
the examples should read public $var1, $var2, $var3 instead of public var1
Page 123:
static public function baz() :: public should come before static
Page 123:
output will display "Hello World... Notice: Undefined property
Page 141:
This chapter says it reviews PDO and database connectivity but it never does... we need to either write something up or take this part out
Page 143:
"one-to-one... correspond to every row in the parent"... should read "each row in the parent"
Page 147:
"suppose we wanted to create a unique index"... but then an ordinary index is created
Page 147:
"isbn ...references book (id)" should say "references book (isbn)"
Page 149:
Ender\'s Game should be escaped with 2 single quotes as such Ender''s Game
Page 153:
sql statement is incomplete, only 2 of 3 tables are joined. Publisher table is missing from the joins
Page 158:
if (is_null(self::$_singleton)) {self::$_singleton = new DB(); - conflicts with the "the getInstance() method, which checks whether the static property $_connection has been iniitialized and, if it hasn't sets it to a new instance of DB
Page 164:
delete this line: function seek($key)
Page 165:
class myData implements Iterator (needed capital I on iterator)
Page 165:
$_myData and $_current needs to remove the underscore
Page 178:
Parsing XML Documents - text is confusing here
Page 184:
$dom->load('library.xml');
Page 184:
should read DomDocument::loadHTMLFile() (capitalize HTML)
Page 185:
DomXpath should read DomXPath
Page 204:
should read " the worst that can happen"
Page 207:
last line, 2nd par - should read "While setting register_globals to Off is the preferred approach"
Page 214:
Reads "Since 1=1 is always true and - begins..." - should read "Since 1=1 is always true and -- begins"
Page 228:
SEEK_CURRENT should be SEEK_CUR
Page 231:
reads "a directory which has the same file as an existing file" - should read "a directory which has the same name as an existing file"
Page 231:
should read "Note that, normally, only the last directory"
Page 231:
should read "Checks if the path is executable
Page 234:
"Stream contexts are created using stream_create_context()" - should read "Stream contexts are created using stream_context_create()"
First Edition Errata
Page 7:
reads "If you need to output data through a function, you can use print() instead". Person reporting comments that "PHP manual makes it clear that print is not really a function but rather a language construct" So perhaps we just need to change the wording.
Page 11:
reads "When converted to a number or a STRING, a boolean becomes ... 0 otherwise". Compare this to
http://www.php.net/manual/en/language.types.string.php
saying:
Boolean FALSE is converted to "" (the empty string).
Page 12:
top line reads "...want to convert to enclosed in brackets"... this should read "want to convert to enclosed in parentheses"
Page 17:
should read $a = int('Test'); //$a==0 ... echo ++$a; //outputs 1. Otherwise the output will read "Tesu" because of the incrementing
Page 19:
lines 2,3: If both bits are either set or unset, the resulting bit is unset
Page 26:
check versus table in the manual http://www.php.net/manual/en/language.operators.php
Page 29:
on while loops: should say "they allow you to perform a series of operations until a condition evaluates to false"
Page 34:
the line "if($oldErrorHandler) will cause an error... need to put global $oldErrorHandler at the beginning of function myErrorHandler(). Also change to $oldErrorHandler = set_error_handler('myErrorHandler');
Page 50:
should read "giving the key for the specific element..."
Page 52:
-- if the two arrays had common elements that also share the same string keys or that have numeric keys (even if they are different) they would only appear once in the end result. This isn't true and should be changed to "if the two arrays had common keys (either string or numeric) they would only appear once in the end result"
Page 53:
var_dump ($a==$c); //should be false
Page 54:
should be echo array_key_exists('a', $a);
Page 54:
should be echo in_array (2, $a);
Page 55:
typo - "note how key key association..."
Pages 56-57: use of reset() is misleading here: only if the $array is passed by-reference to the function, it would be necessary to be reset; otherwise we'll find a brand new reset array inside the function by default.
Page 57:
should be $array = array(1,2,3); ... end ($array); to work with code right after it
Page 67:
"Push and pull" should be "push and pop"
Page 68:
should read "if you intend to use an array as a queue, you can add elements to the beginning and extract them from the end by using the array_unshift() and array_pop() functions".. Also should change the code appropriately
Page 76:
"Here's an escaped backslash - \ - "... should read "...backslash -\\"
Page 77:
echo srtr('abc','a','1'); //(instead of strstr)
Page 79:
strncasecamp instead of strcasencmp
Page 81:
Line 1 should be - "You can use the strspn() function..."
Page 87:
should read "A sign specifier (a plus or minus symbol) ... "
Page 88:
printf("%d", $f); //prints 123
Page 92:
should read "the function returns integer 1 if the match is successful"
Page 98:
should read "Contrary to popular belief, POST is not an inherently more secure way to ..."
Page 99:
2nd par, should read "As you can see, the data has been encoded and appended to the end of "...
Page 99:
should be [direction] not [dir]
Page 99:
Under the [FORM submitted with POST] section, the code says <input type="password" name = "pass' - note the single quote at the end of pass
Page 107:
$data should be $date
Page 109:
Check the "setcookie delete" description
Page 122:
the examples should read public $var1, $var2, $var3 instead of public var1
Page 123:
static public function baz() :: public should come before static
Page 123:
output will display "Hello World... Notice: Undefined property
Page 141:
This chapter says it reviews PDO and database connectivity but it never does... we need to either write something up or take this part out
Page 143:
"one-to-one... correspond to every row in the parent"... should read "each row in the parent"
Page 147:
"suppose we wanted to create a unique index"... but then an ordinary index is created
Page 147:
"isbn ...references book (id)" should say "references book (isbn)"
Page 149:
Ender\'s Game should be escaped with 2 single quotes as such Ender''s Game
Page 153:
sql statement is incomplete, only 2 of 3 tables are joined. Publisher table is missing from the joins
Page 158:
if (is_null(self::$_singleton)) {self::$_singleton = new DB(); - conflicts with the "the getInstance() method, which checks whether the static property $_connection has been iniitialized and, if it hasn't sets it to a new instance of DB
Page 164:
delete this line: function seek($key)
Page 165:
class myData implements Iterator (needed capital I on iterator)
Page 165:
$_myData and $_current needs to remove the underscore
Page 178:
Parsing XML Documents - text is confusing here
Page 184:
$dom->load('library.xml');
Page 184:
should read DomDocument::loadHTMLFile() (capitalize HTML)
Page 185:
DomXpath should read DomXPath
Page 204:
should read " the worst that can happen"
Page 207:
last line, 2nd par - should read "While setting register_globals to Off is the preferred approach"
Page 214:
Reads "Since 1=1 is always true and - begins..." - should read "Since 1=1 is always true and -- begins"
Page 228:
SEEK_CURRENT should be SEEK_CUR
Page 231:
reads "a directory which has the same file as an existing file" - should read "a directory which has the same name as an existing file"
Page 231:
should read "Note that, normally, only the last directory"
Page 231:
should read "Checks if the path is executable
Page 234:
"Stream contexts are created using stream_create_context()" - should read "Stream contexts are created using stream_context_create()"
Subscribe to:
Posts (Atom)