PHP exception and error handling with register_shutdown_function and set_exception_handler
PHP has the crappiest error handling I’ve ever seen. The default behavior is to show all error messages to the user. If you disable this then you get a blank screen instead. The trick is to register an error handler with register_shutdown_function, which is then called if for example memory is exhausted. You could perhaps also use an ErrorDocument 500, but that didn’t work for me.
Here’s the code I’ve used to handle both application exceptions and errors, such as memory limit exceeded. The trick is to have a global variable that indicates whether the script was run successfully or not. Add your code here: “Insert your buggy code here”.
1 $no_errors_detected = false; 2 3 class DispatchErrors 4 { 5 static function handleException($exception) 6 { 7 Logging::error($message); 8 9 header( 'Location: /error500.html' ); 10 } 11 12 static function handleShutdown() 13 { 14 global $no_errors_detected; 15 16 if (!$no_errors_detected) 17 { 18 header( 'Location: /error500.html' ); 19 } 20 } 21 } 22 23 register_shutdown_function(array('DispatchErrors', 'handleShutdown')); 24 set_exception_handler(array('DispatchErrors', 'handleException')); 25 26 # handleShutdown will be called 27 #range(0, 10000000000000000000); 28 29 # handleException will be called 30 #throw new Exception("abcd"); 31 32 # Insert your buggy code here 33 34 $no_errors_detected = true;
A simple and easy to use PHP XML parser
The PHP XML parser:
1 class XML 2 { 3 static function parse($data, $handler, $encoding = "UTF-8") 4 { 5 $parser = xml_parser_create($encoding); 6 7 xml_set_object($parser, $handler); 8 9 xml_set_element_handler($parser, 10 array(&$handler, 'start'), 11 array(&$handler, 'end') 12 ); 13 14 xml_set_character_data_handler( 15 $parser, 16 array($handler, 'content') 17 ); 18 19 $result = xml_parse($parser, $data); 20 21 if(!$result) 22 { 23 $error_string = xml_error_string(xml_get_error_code($parser)); 24 $error_line = xml_get_current_line_number($parser); 25 $error_column = xml_get_current_column_number($parser); 26 27 $message = sprintf("XML error '%s' at line %d column %d", $error_string, $error_line, $error_column); 28 29 throw new Exception($message); 30 } 31 32 xml_parser_free($parser); 33 } 34 }
A result handler:
1 class ResultHandler 2 { 3 var $tag; 4 5 function start ($parser, $tagName, $attributes = null) 6 { 7 echo "start"; 8 $this->tag .= $tagName; # Use .= to work around bug... 9 } 10 11 function end ($parser, $tagName) 12 { 13 echo "end"; 14 $this->tag = null; 15 16 } 17 18 function content ($parser, $content) 19 { 20 echo "$this->tag: $content" ; 21 } 22 }
Then in your code:
1 $xml = "<a>bah</a>"; 2 XML::parse($xml, new ResultHandler());
Note that HTML /XML entities are considered to be tags by PHP ’s XML parser, so your start tag handler will be called three times for this tag, once for “really”, once for “&” and once for ” bad parser”:
1 <data>really & bad parser</data>
I guess this is a bug… You can
PHP file upload gotchas
PHP file upload works in mysterious ways:
1 http://us3.php.net/manual/en/ini.core.php#ini.post-max-size 2 http://fi.php.net/manual/en/features.file-upload.php#73762 3 http://de3.php.net/manual/en/features.file-upload.errors.php
How to generate a pronouncable password with PHP
This is a slight modification of a script I found at PHPFAQ :
1 class Password 2 { 3 static function generate($length) 4 { 5 srand((double)microtime()*1000000); 6 7 $vowels = array("a", "e", "i", "o", "u"); 8 $cons = array("b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr", 9 "cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl"); 10 11 $num_vowels = count($vowels); 12 $num_cons = count($cons); 13 14 $password = ''; 15 16 for($i = 0; $i < $length; $i++) 17 { 18 $password .= $cons[rand(0, $num_cons - 1)] . $vowels[rand(0, $num_vowels - 1)]; 19 } 20 21 return substr($password, 0, $length); 22 } 23 }
To use it try this code:
1 require 'password.php' 2 3 echo Password.generate(10);
It will spit out passwords that are semi-pronouncable.
How to send both HTML and text emails with PHP and PHPMailer
This is an example on how to use PHPMailer to send an HTML email. It also shows how to include a text only version of the same email for clients, such as mutt, that don’t support HTML emails.
1 $mail = new PHPMailer(); 2 3 $mail->IsHTML(true); 4 $mail->CharSet = "text/html; charset=UTF-8;"; 5 $mail->IsSMTP(); 6 7 $mail->WordWrap = 80; 8 $mail->Host = "smtp.thehost.com"; 9 $mail->SMTPAuth = false; 10 11 $mail->From = $from; 12 $mail->FromName = $from; // First name, last name 13 $mail->AddAddress($to, "First name last name"); 14 #$mail->AddReplyTo("reply@thehost.com", "Reply to address"); 15 16 $mail->Subject = $subject; 17 $mail->Body = $htmlMessage; 18 $mail->AltBody = $textMessage; # This automatically sets the email to multipart/alternative. This body can be read by mail clients that do not have HTML email capability such as mutt. 19 20 if(!$mail->Send()) 21 { 22 throw new Exception("Mailer Error: " . $mail->ErrorInfo); 23 }