January 18th, 2010

While parts of the world are still freezingly cold, Taipei is already slowly warming up to 21 degrees, blue skies and sunshine. Sadly enough as this is my last day in the city for probably a very long time. Tomorrow I will fly off to a new life in the old country. After twelve years of travelling all over the island this place really feels like home.
Today was also the last day that I could take the second and final part of the MySQL 5.0 Developer certifications. The US$ 200 SUN exam voucher I had purchased earlier is only valid in Taiwan. Taking the exam in the Netherlands was thus not an option.
Looking back at my previous blog entry about the MySQL Examens — it took me 20 days to prepare this part of the exam. I studied by browsing through the exam book at breakfast and before going to bed and added some more serious study blocks to work through all the exercise questions.
The second exam was quite a bit harder than the first one mostly because it asked many interesting (and confusing/tricky) questions about inner, left and right joins and of course sub-queries.
But what I found the hardest chapter in the book Chapter 18. Stored Procedures and Functions in which a complete programming language is introduced using only about 2-3 examples was good for only a few questions. Just pay attention to the correct syntax.
Overal I really enjoyed studying for the exam. The MySQL exam preparation book is excellent and covers the exam exactly.
Tags: mysql
Posted in PHP | 2 Comments - getting there! »
December 30th, 2009

As promised in my last post (twenty days ago — life has been busy!) I am working through the MySQL Developer 5.0 examinations. I have just completed the first of two exams and I am trying to find time to cram for the second exam.
There are plenty of changes going on here — the original exam MySQL exam provider was changed this year from Pearson Vu to Prometric as Sun Microsystems acquired MySQL.
And now of course Sun is in limbo as it in turn is being acquired by Oracle — a deal being blocked in Europe because of , yes : MySQL. For a by the minute discussion of what is going on there just keep track of the postings at Planet MySQL.
Expect many FAQ’s to be out of date. It is better to check the MySQL Certification forum for the latest changes. The person to note is David Stokes who is the MySQL certification manager and who posts regularly to this forum. Read the rest of this entry »
Tags: exam, mysql
Posted in PHP | 1 Comment already!»
December 8th, 2009

taipei 101 by orange tuesday @ flickr
I have been busy these last couple of weeks preparing for the Zend Certified Engineer / PHP5 exam. Although I have been using PHP for years – I never had a need to “prove” this. That might change in a few months as I start looking for a new job. Doing the Zend exam in preparation of this sounded like a good start. My first step was to order the Zend PHP5 Certification Study Guide by Davey Shafik and Ben Ramsey from Amazon.
The difficulty is not so much in the technologies — most things in PHP are very straightforward — but the sheer scope of what PHP covers and the potential for in dept questions. The exam covers programming basics such as converting hex / octal and decimal, XML & XPath, Web programming, OOP, Databases, Pattern theory etc. The study guide covers most topics but it alone is not enough to pass the exam. It will set you on the right path — but you really need to dive deeper. Read the rest of this entry »
Tags: exam, PHP, zend
Posted in PHP | 6 Comments - getting there! »
December 4th, 2009
I am starting to use Google Chrome more often and doing this made me notice that one of my Javascript functions wasn’t working properly. A little bit of digging revealed that Chrome did not like the XML I was feeding it.
Entity '¡' not defined
The code generating the XML was using the PHP function htmlentities to filter its output but this does not generate valid XML. Named entities such as " and & need to be represented by their Unicode values: " and &
A handy table with all the required replacements can be found at Carlos Ouro’s website.
Below is a simple function that replaces all the named HTML entities found in a string with their numeric HTML/XML counterparts.
Example Usage
# Test #1
$test = "" Hello World! "";
echo xmlentities
($test) . PHP_EOL
;
# Test #2
$test = "\"Hello World\"";
echo xmlentities
( htmlentities($test) ) . PHP_EOL
;
XMLEntities function
function xmlentities
($string)
{
// Convert HTML entities to XML
// http://techtrouts.com/webkit-entity-nbsp-not-defined-convert-html-entities-to-xml/
$htmlentities = array( ""","&","<",">"," ","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ","€");
$xmlentities = array(""","&","<",">"," ","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß","à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï","ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ","€" );
// HTML entities are case-sensitive (http://htmlhelp.com/reference/html40/entities/)
return str_replace($htmlentities,$xmlentities,$string);
}
Tags: PHP, xml
Posted in PHP | 2 Comments - getting there! »
November 24th, 2009

Google Apps has great benefits for small companies. There is little need to maintain your own IT infrastructure, a simple ADSL line attached to a tiny internal network is sufficient for the majority of tasks.
But how do you move an existing company to Google Apps?
A company I have been working with uses Thunderbird for its e-mail.
Moving should have been straightforward as Google provides their own migration tool : the e-mail uploader.
The development of this program however appears stagnant and its bugs are not being fixed. Strange considering how important Google Apps must be for Google.
For me the problem was that 40-50% of the Thunderbird e-mails in the mail store were not being uploaded because the Google Uploader complained that there was something wrong with the date format.
The bug related to this has been open for over a year.
If I wanted to continue I needed to find my own solution or give up on migrating altogether.
A quick browse through the Zend Framework manual showed that it can read MBox files (Thunderbirds mailbox format) through the Zend_Mail_Storage* class and communicate with Google using the Zend_Gdata* classes.
The exercise left was to bind it all together into a working PHP script that would take my mailboxes and upload them to Google.
Having done this and having succesfully uploaded several multi-Gigabyte sized mailboxes I have uploaded my code (’googlemailappuploader’) to Google Code.
If you find yourself in a similar situation — I hope you find it usefull. Leave me a comment if something is unclear.
Tags: google, Google Apps, php5, zend framework
Posted in PHP | 2 Comments - getting there! »
November 13th, 2009

Time to debug by henribergius @ flickr
This post contains my installation notes on how to setup the Eclipse PHP IDE with support for XDebug remote debugging in a mixed Windows/Ubuntu development environment.

Debugging PHP with XDebug in Eclipse
One of the great things of writing PHP code in a modern IDE is that you can step through your code, set break points and inspect variables. No more endless print/echo statements, or including your own custom logging code every few lines.
The war to decide the best IDE is far from over. If you would like to write PHP code and are looking for a free IDE (Integrated Development Environment) then both Eclipse PHP and the Netbeans IDE are two very strong candidates. Both are written in JAVA. For this post I concentrate on my own favorite: Eclipse. If you would like to compare several other PHP IDE’s then Davey Shafik has a great table comparing IDE features on his site.
Debugging is done through a remote debugger called XDebug. It ties into the PHP runtime on your server allowing Eclipse to communicate with your scripts / web pages. As soon as you start debugging a web page, Eclipse will call your webserver but also pass a couple of parameters. On seeing these parameters (XDEBUG_SESSION_START/KEY), XDebug will start and connect to Eclipse over a TCP/IP connection. From here on Eclipse can control the execution of the script on the webserver.
My development setup Read the rest of this entry »
Tags: eclipse, php5, xdebug
Posted in PHP | 3 Comments - getting there! »
November 10th, 2009
After reading up on PHP5 object orientation I decided to build a little test class that implemented as many of the OOP features offered by PHP5 as I could find.
Think magic functions, constants, cloning, getters and setters, abstract, final, inheritance, serialization and of course var_export support.
If I missed any concepts feel free to drop a note.
<?php
/* The Ultimate PHP5 OOP Class
*
* Implements most of PHP5's OOP functionality in a single demonstration
*/
/* PHP_VERSION_ID is available as of PHP 5.2.7, if our
* version is lower than that, then emulate it. Some of the
* functionality we test here is only available in 5.3.0 and
* higher.
*/
if(!defined('PHP_VERSION_ID'))
{
$version = explode('.',PHP_VERSION);
define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2]));
}
/* Interfaces specify a set of functions that a class MUST
* implement.
*/
interface DemoInterface
{
public function InterfaceTest();
}
/* Abstract classes cannot be instantiated. They define concepts that
* their derived classes must implement.
*/
abstract class DemoAbstract
{
/* Constructor
*
*/
public function __construct()
{
$this->LogEntry(__CLASS__,__METHOD__);
}
/* LogEntry
*
* Reports on each methods entry. Defined in the parent class so that
* we can call it from this constructor as well.
*
* @param string Methodname (from __METHOD__)
*/
public function LogEntry($methodName)
{
echo "{$methodName} Called" . PHP_EOL;
}
abstract public function AbstractTest();
}
/* The DemoPHP5Class is marked as "final". Because of this selfish act
* nobody is able to derive from this work and create their own sub class.
*/
final class DemoPHP5Class extends DemoAbstract implements DemoInterface
{
/* Class Constants cannot be changed */
const VERSION = '1.0';
/* Private members are only available inside this class */
private $_className;
private $_constructorName;
private $_fileName;
private $_instanceCount;
/* Location for overloaded data. */
private $_data = array();
/* As the class is marked final there really is not point in declaring
* any protected (accessible by derived classes) variables but
* for good measure we include one.
*/
protected $_meaningOfLife;
/* The constructor is labeled as final. Because of this derived
* classes are unable to implement their own constructor.
*/
final function __construct()
{
parent::__construct(); // Calling the parent constructor
$this->_className = __CLASS__; // Magic constants
$this->_constructorName = __METHOD__;
$this->_fileName = __FILE__;
$this->_instanceCount = 0; // Original, not a clone
$this->_meaningOfLife = 42; // No need to say more
$this->LogEntry(__CLASS__,__METHOD__);
}
final function __destruct()
{
$this->LogEntry(__METHOD__);
}
/* Implements the Abstract members from the DemoAbstract
* class.
*
* @returns string Notification message
*/
public function AbstractTest()
{
$this->LogEntry(__METHOD__);
}
/* Implements the DemoInteface
*
* @returns string Notification message
*/
public function InterfaceTest()
{
$this->LogEntry(__METHOD__);
}
/* Static functions are not part of an instance
* and can only be called through "classname::staticmethod"
*/
public static function StaticTest($number)
{
/* Note how LogEntry is NOT static, but we can still call it */
/* A warning is generated in STRICT mode */
parent::LogEntry(__CLASS__,__METHOD__);
echo "StaticTest call with ({$number}) succesfull" . PHP_EOL;
}
/* Returns the name of the class
*
* @returns string Name of the class as discovered by the constructor
*/
public function GetClassName()
{
$this->LogEntry(__METHOD__);
return $this->_className;
}
/* Set the meaning of life
*
* @param int Meaning of life
* @thows Exception On invalid input
* @returns this Allow for chaining of calls
*/
public function SetMeaningOfLife($meaningOfLife)
{
$this->LogEntry(__METHOD__);
if (is_int($meaningOfLife))
{
$this->_meaningOfLife = $meaningOfLife;
}
else
{
throw new Exception('Meaning of Life doubted');
}
return $this;
}
/* Returns the meaning of life
*
* @returns int Meaning of life as a core value
*/
public function GetMeaningOfLife()
{
$this->LogEntry(__METHOD__);
return $this->_meaningOfLife;
}
/* Returns the instance count
*
* @returns int Instance count
*/
public function GetInstanceCount()
{
return $this->_instanceCount;
}
/* Magic Methods
*
* These methods have special meaning inside of PHP5.
*/
/* Return a string description of the class
*
* @returns string Whatever the class fancies. Usually a description
*/
public function __toString()
{
$this->LogEntry(__METHOD__);
return '__toString called ; the meaning of life is our domain' . PHP_EOL;
}
/* From PHP 5.3.0 its possible to "invoke" a class, using it like
* a function. Eg. 'DemoPHP5Class(50)'.
*/
public function __invoke($x)
{
$this->LogEntry(__METHOD__);
echo "__invoke was called with {$x}" . PHP_EOL;
}
/* PHP 5 allows the simulation of properties. If a property does not
* exist when attempting to write the __set method is called giving
* you an opportunity to handle the variable yourself.
*/
/* Called when a not-class defined property is set by the user. For
* example "DemoPHP5Class->FooBar = 500". We add an entry to the
* $this->_data table.
*
* @param string A valid name
* @param undefined Any valid PHP value
* @throws Exception Only strings are considered valid names
*/
public function __set($name,$value)
{
$this->LogEntry(__METHOD__);
if (is_string($name)) {
$this->_data[$name] = $value;
return;
}
throw new Exception('Invalid Property name');
}
/* Called when a not class defined property is retrieved. We
* attempt to satisfy the called by checking $this->_array.
*
* @param string A valid name
* @throws Exception When the property is not defined
* @returns undefined Value of the named property
*/
public function __get($name)
{
$this->LogEntry(__METHOD__);
if (is_string($name) &amp;amp;amp;amp;&amp;amp;amp;amp; array_key_exists($name, $this->_data))
return $this->_data[$name];
throw new Exception("Attempted to read undefined proporty");
}
/* This method is called whenever we try to access an inaccessible
* property. We check $this->_data to see if a matching key exists.
*
* @param string A valid string property name
* @returns bool True on finding the property in the array
*/
public function __isset($name)
{
$this->LogEntry(__METHOD__);
if (is_string($name) &amp;amp;amp;amp;&amp;amp;amp;amp; array_key_exists($name, $this->_data))
return true;
}
/* This method is called when unset is called on an inaccessible
* class property. We check $this->_data and try to unset it.
*
* @param string A valid string property name
* @throws Exception The property must exist, mmmm, ok?
*/
public function __unset($name)
{
$this->LogEntry(__METHOD__);
if (is_string($name) &amp;amp;amp;amp;&amp;amp;amp;amp; array_key_exists($name, $this->_data))
unset($this->_data[$name]);
else
throw new Exception("Unsetting non-existant property");
}
/* When a class is serialized (eg. put away into cold storage)
* it is checked for a __sleep method. If it exists it is called
* to allow the class to prepare a list with names of its most important
* variables for safe storage.
*
* @returns array Critical variables that need to be stored
*/
public function __sleep()
{
$this->LogEntry(__METHOD__);
return array("_meaningOfLife","_className","_constructorName",
"_fileName","_data");
}
/* On deserialization the class needs to re-initialise.
* This is a good point to re-establish the database connection and
* any other critical (but not storable) resources.
*/
public function __wakeup()
{
$this->LogEntry(__METHOD__);
}
/* When an object is "cloned" an exact copy is created. This is not
* always desirable (think resource handles that are now shared by two
* objects). The __clone magic function is called on the COPY and
* allows it to initialise any variables it sees fit.
*/
public function __clone()
{
$this->LogEntry(__METHOD__);
// Clones know they are copies because only the original
// object has an _instanceCount value of 0.
$this->_instanceCount++;
}
/* Used by var_export which allows the creation of a PHP evaluable
* string that would re-create this object.
*
* See also: http://www.thoughtlabs.com/2008/02/02/phps-mystical-__set_state-method/
*/
public static function __set_state($an_array)
{
echo "static::__set_state called" . PHP_EOL;
// Create a new class, set its parameters and
// exit.
$tmp = new DemoPHP5Class();
foreach($an_array as $name => $value)
$tmp->$name = $value;
return $tmp;
}
}
/* Enable strict warnings */
error_reporting(E_ALL | E_STRICT);
/* Test Code */
$demo = new DemoPHP5Class();
/* Example of a class constant */
echo "Class version: " . DemoPHP5Class::VERSION . PHP_EOL;
/* Test #1: Abstract method in parent class, simply call it*/
$demo->AbstractTest();
/* Test #2: Call the Interface member */
$demo->InterfaceTest();
/* Test #3: Call of a static member */
DemoPHP5Class::StaticTest(20);
/* Test #4: Call a regular get method */
$demo->GetClassName();
/* Test #5: Call a regular set method with valid param */
$demo->SetMeaningOfLife(43);
/* Test #6: Call a regular set method with INVALID param */
try {
$demo->SetMeaningOfLife(42.5);
}
catch (Exception $e) {
echo "Exception Caught OK" . PHP_EOL;
}
/* Test #7: Try to print the object , calling __tostring() */
echo $demo;
/* Test #8: Invoke the object , bit like magic really */
/* only available from PHP 5.3.0 up */
if (PHP_VERSION_ID > 50300)
$demo('abacradaba');
/* Test #9: Set an non-existant member of the object, causing
* a call to __set, which will emulate/store the value
*/
$demo->non_existing_member = 256;
/* Test #10: Confirm that the new member has been set */
if (isset($demo->non_existing_member))
echo 'Confirmed existance of \$demo->non_existing_member' . PHP_EOL;
else
echo 'Failed to verify setting of \$demo->non_existing_member' . PHP_EOL;
/* Test #11: Retrieve the non-existing member, causing a call
* to __get, which will attempt to retrieve it from the internal
* storage array.
*/
if ($demo->non_existing_member == 256)
echo "Retrieval of \$demo->non_existing_member succesfull" . PHP_EOL;
else
echo "Retrieval of \$demo->non_existing_member FAILED" . PHP_EOL;
/* Test #12: Remove the member, and test if this was succesfull */
unset($demo->non_existing_member);
if (!isset($demo->non_existing_member))
echo 'Confirmed removal of \$demo->non_existing_member' . PHP_EOL;
else
echo 'Failed to remove \$demo->non_existing_member' . PHP_EOL;
/* Test #13: Serialization , put the object to sleep and turn it
* into a form that we can store away savely.
*/
$serialized_data = serialize( $demo );
$demo2 = unserialize($serialized_data);
/* Test #14: Cloning. After cloning the object the clone should
* have a higher instance value than the original object because
* of the additional changes made by __clone
*/
$demo3 = clone $demo;
if ($demo3->GetInstanceCount() > $demo->GetInstanceCount())
echo "Succesfull cloning; instance count has been increased. " . PHP_EOL;
else
echo "Failed to clone; instance count is the same. " . PHP_EOL;
/* Test 15: Var_Export must produce valid PHP code that can be
* run through 'eval'. It has trouble with objects , so it needs
* a little help from the __set_state magic function
*/
eval('$demo4 = ' . var_export($demo, true) . ';');
/* Remember, we modified the meaning of life to 43 in $demo */
if ($demo4->GetMeaningOfLife()==$demo->GetMeaningOfLife())
echo "Succesfull re-creation of the \$demo class" . PHP_EOL;
else
echo "Failed to recreate. The meaning of life was lost. " . PHP_EOL;
/* EOF */
?>
Tags: oop, php5, zendexam
Posted in PHP | 1 Comment already!»
November 9th, 2009

XML Summer School by psd @ flickr
Below are some of the notes I made while preparing for the Zend PHP5 exam. They are a quick memory jog of how SimpleXML works and its limitations.
The SimpleXML extension provides easier access to XML files. It is simpler to use but also much more limited than the DOM XML extension. If your document makes use of XML namespaces (ns:foo) then it is better NOT to use SimpleXML as it will become anything but simple.
SimpleXML only supports XML 1.0. If fed an XML 1.1 document it will show “Unsupported version ‘1.1′” warnings, but will continue and attempt to read the file.
Removing elements is not really supported and the opportunities for modification are limited. SimpleXML is best used for straightforward reading and using of XML files. Read the rest of this entry »
Tags: php5, simplexml, zendexam
Posted in PHP | 2 Comments - getting there! »