<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Derick Rethans - tag: php</title>
    <link>http://derickrethans.nl/feed-php.xml</link>
    <description>This feed shows the latest 15 items with the tag php</description>
    <language>en-us</language>
    <copyright>All rights reserved - Derick Rethans</copyright>
    <managingEditor>derick@derickrethans.nl (Derick Rethans)</managingEditor>
    <pubDate>Wed, 01 Sep 2010 07:51:05 +0000</pubDate>
    <lastBuildDate>Wed, 01 Sep 2010 07:51:05 +0000</lastBuildDate>
    <generator>eZ Components Feed dev (http://ezcomponents.org/docs/tutorials/Feed)</generator>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <ttl>60</ttl>
    <item>
      <title>Collecting Garbage: PHP's take on variables</title>
      <link>http://derickrethans.nl/collecting-garbage-phps-take-on-variables.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="collecting_garbage_php_s_take_on_variables"/&gt;Collecting Garbage: PHP's take on variables&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Tuesday, August 31st 2010, 09:23 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;This is the first part of three-parts column that was originally published in the &lt;a href="http://www.phparch.com/magazine/2009/april/"&gt;April 2009&lt;/a&gt; issues of &lt;a href="http://www.phparch.com/magazine"&gt;php|architect&lt;/a&gt;.&lt;/p&gt;
      &lt;hr/&gt;
      &lt;p&gt;In this three part column I will explain the merits of the new Garbage Collection (also known as GC) mechanism that is part of PHP 5.3. Before we start with the intricate details of PHP's new GC engine I will explain why it is actually needed. This, combined with an introduction how PHP deals with variables in general is explained in this first part of the column. The second part will cover the solution and some notes on the GC mechanism itself, and the third part covers some implications of the GC mechanism, as well as some benchmarks. But now first on to the introduction.&lt;/p&gt;
      &lt;p&gt;PHP stores variables in containers called a "zval". A zval container contains besides the variable's type and value, also two additional bits of information. The first one is called "is_ref" and contains a boolean value whether this variable is part of a "reference set". With this bit PHP's engine knows how to differentiate between normal variables, and references. However, PHP has user-land references—as created by the &amp; operator, but also an internal reference counting mechanism to optimize memory usage. The second piece of additional information, called "refcount", contains how many variables names—also called symbols—point to this one zval container. All symbols are stored in a symbol table, of which there is one per scope. There is a scope for the main script (ie, the one requested through the browser), as well as for every function or method.&lt;/p&gt;
      &lt;p&gt;A zval container is created when a new variable is created with a constant value, such as:&lt;/p&gt;
      &lt;pre&gt;$a = "new string";

&lt;/pre&gt;
      &lt;p&gt;In this case the new symbol name "a" is created in the current scope, and a new variable container is created with type "string", value "new string". The "is_ref" bit is by default set to "false" because no user-land reference has been created. The "refcount" is set to "1" as there is only one symbol that makes use if this variable container. Also, if the "refcount" is "1", "is_ref" is always "false". If you have &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; installed you can display this information by calling:&lt;/p&gt;
      &lt;pre&gt;xdebug_debug_zval('a');

&lt;/pre&gt;
      &lt;p&gt;which displays:&lt;/p&gt;
      &lt;pre&gt;a: (refcount=1, is_ref=0)='new string'

&lt;/pre&gt;
      &lt;p&gt;Assigning this variable to another variable name, increases the refcount:&lt;/p&gt;
      &lt;pre&gt;$a = "new string";
$b = $a;
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays:&lt;/p&gt;
      &lt;pre&gt;a: (refcount=2, is_ref=0)='new string'

&lt;/pre&gt;
      &lt;p&gt;The refcount is "2" here, because the same variable container is linked with both "a" and "b". PHP is smart enough not to copy the actual variable container when it is not necessary. Variable containers get destroyed when the "refcount" reaches zero. The "refcount" gets decreased by one for each symbol linked to the variable container leaves the scope (f.e. if the function ends) or when unset() is called on a symbol. The following example shows that:&lt;/p&gt;
      &lt;pre&gt;$a = "new string";
$c = $b = $a;
xdebug_debug_zval( 'a' );
unset( $b, $c );
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays:&lt;/p&gt;
      &lt;pre&gt;a: (refcount=3, is_ref=0)='new string'
a: (refcount=1, is_ref=0)='new string'

&lt;/pre&gt;
      &lt;p&gt;If we now call "unset( $a );" the variable container, including the type and value will be removed from memory.&lt;/p&gt;
      &lt;p&gt;Things get a tad more complex with compound types such as arrays and objects. Instead of a scalar value, arrays and objects store their properties in a symbol table of their own. This means that the following example creates &lt;strong&gt;three&lt;/strong&gt; zval containers:&lt;/p&gt;
      &lt;pre&gt;$a = array( 'meaning' =&gt; 'life', 'number' =&gt; 42 );
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays (after formatting):&lt;/p&gt;
      &lt;pre&gt;a: (refcount=1, is_ref=0)=array (
        'meaning' =&gt; (refcount=1, is_ref=0)='life',
        'number' =&gt; (refcount=1, is_ref=0)=42
)

&lt;/pre&gt;
      &lt;p&gt;Graphically, it looks like:&lt;/p&gt;
      &lt;img src="/images/content/gc-part1-figure1.png" alt="gc-part1-figure1.png"/&gt;
      &lt;p&gt;You can see the three zval containers here: "a", "meaning" and "number". Similar rules apply for increasing and decreasing "refcounts". Below we add another element to the array, and set it's value to the contains of an already existing element:&lt;/p&gt;
      &lt;pre&gt;$a = array( 'meaning' =&gt; 'life', 'number' =&gt; 42 );
$a['life'] = $a['meaning'];
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays (after formatting):&lt;/p&gt;
      &lt;pre&gt;a: (refcount=1, is_ref=0)=array (
        'meaning' =&gt; (refcount=2, is_ref=0)='life',
        'number' =&gt; (refcount=1, is_ref=0)=42,
        'life' =&gt; (refcount=2, is_ref=0)='life'
)

&lt;/pre&gt;
      &lt;p&gt;Graphically, it looks like:&lt;/p&gt;
      &lt;img src="/images/content/gc-part1-figure2.png" alt="gc-part1-figure2.png"/&gt;
      &lt;p&gt;From the above we see that both the old and new array element now point to a zval container which "refcount" is "2". Of course there are now two zval containers, but they are the same one. The &lt;a href="http://xdebug.org/docs/all_functions#xdebug_debug_zval"&gt;xdebug_debug_zval()&lt;/a&gt; function does not show this, but could, by also displaying the memory pointer. Removing an element from the array is like removing a symbol from a scope. By doing so, the "refcount" of a container that an array element points to is decreased. Again when the "refcount" reaches zero, the variable container is removed from memory. Again an example to show this:&lt;/p&gt;
      &lt;pre&gt;$a = array( 'meaning' =&gt; 'life', 'number' =&gt; 42 );
$a['life'] = $a['meaning'];
unset( $a['meaning'], $a['number'] );
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays (after formatting):&lt;/p&gt;
      &lt;pre&gt;a: (refcount=1, is_ref=0)=array (
        'life' =&gt; (refcount=1, is_ref=0)='life'
)

&lt;/pre&gt;
      &lt;p&gt;Now, things get interesting if we add the array itself as an element of the array, which we do in the next example—in which I also sneaked in an reference operator as otherwise PHP would create a copy here:&lt;/p&gt;
      &lt;pre&gt;$a = array( 'one' );
$a[] =&amp; $a;
xdebug_debug_zval( 'a' );

&lt;/pre&gt;
      &lt;p&gt;which displays (after formatting):&lt;/p&gt;
      &lt;pre&gt;a: (refcount=2, is_ref=1)=array (
        0 =&gt; (refcount=1, is_ref=0)='one',
        1 =&gt; (refcount=2, is_ref=1)=...
)

&lt;/pre&gt;
      &lt;p&gt;Graphically, it looks like:&lt;/p&gt;
      &lt;img src="/images/content/gc-part1-figure3.png" alt="gc-part1-figure3.png"/&gt;
      &lt;p&gt;You can see that the array variable ("a") as well as the second element ("1") now point to a variable container that has a "refcount" of "2". The "..." in the display above shows that there is recursion involved, which of course in this case it means that the "..." points back to the original array.&lt;/p&gt;
      &lt;p&gt;Just like before, unsetting a variable removes the symbol, and the reference count of the variable container it points to is decreased by one. So if we unset variable $a after running the above code, the reference count of the variable container that $a and element "1" point to gets decreased by one, from "2" to "1". This can be represented like:&lt;/p&gt;
      &lt;pre&gt;(refcount=1, is_ref=1)=array (
        0 =&gt; (refcount=1, is_ref=0)='one',
        1 =&gt; (refcount=1, is_ref=1)=...
)

&lt;/pre&gt;
      &lt;p&gt;Graphically, it looks like:&lt;/p&gt;
      &lt;img src="/images/content/gc-part1-figure4.png" alt="gc-part1-figure4.png"/&gt;
      &lt;p&gt;Although there is no symbol in any scope pointing to this structure anymore, it can not be cleaned up either because the array element "1" still points to this same array. Because there is no external symbol pointing to it, there is no way for a user to clean up this structure anymore, and thus you get a memory leak. Fortunately, PHP will clean up this data structure at the end of the request, but before then this is taking up valuable space in memory. The mentioned situation happens often if you're implementing parsing algorithms or other things where you have a child point back at a "parent" element. The same situation can also happen with objects of course, where it actually happens easier as objects are always implicitly used by reference.&lt;/p&gt;
      &lt;p&gt;This might not be a problem if this only happens once or twice, but if there is thousands, or even millions of these memory losses, this obviously starts being a problem. Especially in long running scripts, such as daemons where the request basically never ends, or in large sets of unit tests. The latter caused problems for us while running the unit tests for the Template component of the eZ Components library. In some cases it would require over 2 GiB of memory, which our test server didn't quite have.&lt;/p&gt;
      &lt;p&gt;With that we conclude this introduction, for more information on how PHP deals with variables I can point you at June 2005 issue of php|architect. That article is also available on-line as PDF (&lt;a href="http://derickrethans.nl/files/phparch-php-variables-article.pdf"&gt;http://derickrethans.nl/files/phparch-php-variables-article.pdf&lt;/a&gt;). In the next installment, we're going to discuss the solution to the memory leak problem with circular references.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201008310923</guid>
      <pubDate>Tue, 31 Aug 2010 08:23:00 +0000</pubDate>
    </item>
    <item>
      <title>64-bit integers in MongoDB</title>
      <link>http://derickrethans.nl/64bit-ints-in-mongodb.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="id_64-bit_integers_in_mongodb"/&gt;64-bit integers in MongoDB&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Monday, August 9th 2010, 14:23 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;The current project that I'm working on relies heavily on &lt;a href="http://mongodb.org"&gt;MongoDB&lt;/a&gt;, a bridge between key-value stores and traditional RDBMS systems. Users in this project are identified by their Facebook &lt;a href="http://wiki.developers.facebook.com/index.php/User_ID"&gt;UserID&lt;/a&gt;, which is a "64-bit int datatype". Unfortunately, the &lt;a href="http://github.com/mongodb/mongo-php-driver"&gt;MongoDB PHP Driver&lt;/a&gt; only had support for 32-bit integers causing problems for newer users of Facebook. For those users, their nice long UserID was truncated to only 32 bits which didn't quite make the application work.&lt;/p&gt;
      &lt;p&gt;MongoDB stores documents internally in something called &lt;a href="http://bsonspec.org/"&gt;BSON&lt;/a&gt; (Binary &lt;a href="http://www.json.org/"&gt;JSON&lt;/a&gt;). BSON has two integer types, a 32-bit signed integer type called &lt;code&gt;INT&lt;/code&gt; and a 64-bit signed integer type called &lt;code&gt;LONG&lt;/code&gt;. The documentation of the MongoDB PHP driver on &lt;a href="http://uk2.php.net/manual/en/mongo.types.php"&gt;types&lt;/a&gt; says (or used to say, depending on when you're reading this) that only the 32-bit signed integer type is supported because "PHP does not support 8 byte integers". That's not quite true. PHP's integer type supports 64-bit on the platforms where the C-data type &lt;code&gt;long&lt;/code&gt; is 64 bits. That is generally on every 64-bit platform (where PHP is compiled for 64 bits); except on Windows, where the C-data type &lt;code&gt;long&lt;/code&gt; is always only 32 bits.&lt;/p&gt;
      &lt;p&gt;Whenever a PHP integer is sent to MongoDB, the driver would use the 32 least significant bits to store the number as part of the document. The example here shows what happens (on a 64-bit platform):&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$m = new Mongo();
$c = $m-&gt;selectCollection('test', 'inttest');
$c-&gt;remove(array());

$c-&gt;insert(array('number' =&gt; 1234567890123456));

$r = $c-&gt;findOne();
echo $r['number'], "\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;shows:&lt;/p&gt;
      &lt;pre&gt;int(1015724736)

&lt;/pre&gt;
      &lt;p&gt;In binary:&lt;/p&gt;
      &lt;pre&gt;1234567890123456 = 100011000101101010100111100100010101011101011000000
      1015724736 =                      111100100010101011101011000000

&lt;/pre&gt;
      &lt;p&gt;Truncating data is obviously not a very good idea. In order to address this issue we could just allow for the native PHP integer type to be used when storing data from PHP into MongoDB. But instead of changing how the MongoDB driver works by default I've added the new setting &lt;code&gt;mongo.native_long&lt;/code&gt; — simply because otherwise we might be breaking applications. With the &lt;code&gt;mongo.native_long&lt;/code&gt; setting enabled, we see the following result instead of the outcome of the script above:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
ini_set('mongo.native_long', 1);
$c-&gt;insert(array('number' =&gt; 1234567890123456));

$r = $c-&gt;findOne();
var_dump($r['number']);
?&gt;

&lt;/pre&gt;
      &lt;p&gt;This script shows:&lt;/p&gt;
      &lt;pre&gt;int(1234567890123456)

&lt;/pre&gt;
      &lt;p&gt;On &lt;strong&gt;64-bit platforms&lt;/strong&gt;, the &lt;code&gt;mongo.native_long&lt;/code&gt; setting allows for 64-bit integers to be stored in MongoDB. The MongoDB data type that is used in this case is the BSON LONG, instead of the BSON INT that is used if this setting is turned off. The setting &lt;em&gt;also&lt;/em&gt; changes the way how BSON LONGs behave when they are read back from MongoDB. Without &lt;code&gt;mongo.native_long&lt;/code&gt; enabled, the driver would convert every BSON LONG to a PHP double which results in the loss of precision. You can see that in the following example:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
ini_set('mongo.native_long', 1);
$c-&gt;insert(array('number' =&gt; 12345678901234567));

ini_set('mongo.native_long', 0);
$r = $c-&gt;findOne();
var_dump($r['number']);
?&gt;

&lt;/pre&gt;
      &lt;p&gt;This script shows:&lt;/p&gt;
      &lt;pre&gt;float(1.2345678901235E+16)

&lt;/pre&gt;
      &lt;p&gt;On &lt;strong&gt;32-bit platforms&lt;/strong&gt;, the &lt;code&gt;mongo.native_log&lt;/code&gt; setting changes nothing for storing integers in MongoDB: the integer is stored as a BSON INT as before. However, when the setting is enabled and a BSON LONG is read from MongoDB a &lt;a href="http://uk2.php.net/manual/en/class.mongocursorexception.php"&gt;MongoCursorException&lt;/a&gt; is thrown alerting you that the data could not be read back without losing precision:&lt;/p&gt;
      &lt;pre&gt;MongoCursorException: Can not natively represent the long 1234567890123456 on this platform

&lt;/pre&gt;
      &lt;p&gt;If the setting is not enabled, a BSON LONG is converted to a PHP float in order to avoid breaking backwards compatibility with the current behaviour.&lt;/p&gt;
      &lt;p&gt;Although the &lt;code&gt;mongo.native_long&lt;/code&gt; settings allows for 64-bit support on 64-bit platforms, it doesn't provide much for 32-bit platforms except preventing loss of precision while reading BSON LONGs—and then by just throwing an exception.&lt;/p&gt;
      &lt;p&gt;As part of making 64-bit integers work reliably with MongoDB, I've also added two new classes: &lt;code&gt;MongoInt32&lt;/code&gt; and &lt;code&gt;MongoInt64&lt;/code&gt;. These two classes are simple wrappers around a string representation of a number. They are instantiated like this:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$int32 = new MongoInt32("32091231");
$int64 = new MongoInt64("1234567980123456");
?&gt;

&lt;/pre&gt;
      &lt;p&gt;You can use those objects in normal insert and update queries just like normal numbers:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$m = new Mongo();
$c = $m-&gt;selectCollection('test', 'inttest');
$c-&gt;remove(array());

$c-&gt;insert(array(
        'int32' =&gt; new MongoInt32("1234567890"),
        'int64' =&gt; new MongoInt64("12345678901234567"),
));

$r = $c-&gt;findOne();
var_dump($r['int32']);
var_dump($r['int64']);
?&gt;

&lt;/pre&gt;
      &lt;p&gt;Which shows:&lt;/p&gt;
      &lt;pre&gt;int(1234567890)
float(1.2345678901235E+16)

&lt;/pre&gt;
      &lt;p&gt;As you can see, nothing is changed with how values are returned. A BSON INT is still returned as an integer, and a BSON LONG as a double. If we turn on the &lt;code&gt;mongo.native_long&lt;/code&gt; setting then the BSON LONG that was stored through the &lt;code&gt;MongoInt64&lt;/code&gt; class is returned as a PHP integer on 64-bit platforms, and a MongoCursorException is thrown on 32-bit platforms.&lt;/p&gt;
      &lt;p&gt;In order to received 64-bit integers back from MongoDB on 32-bit platforms, I've added another setting: &lt;code&gt;mongo.long_as_object&lt;/code&gt;. This will (on any platform) return a BSON LONG as stored in MongoDB as a &lt;code&gt;MongoInt64&lt;/code&gt; object. The following script demonstrates that:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$m = new Mongo();
$c = $m-&gt;selectCollection('test', 'inttest');
$c-&gt;remove(array());

$c-&gt;insert(array(
        'int64' =&gt; new MongoInt64("12345678901234567"),
));

ini_set('mongo.long_as_object', 1);
$r = $c-&gt;findOne();
var_dump($r['int64']);
echo $r['int64'], "\n";
echo $r['int64']-&gt;value, "\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;This script outputs:&lt;/p&gt;
      &lt;pre&gt;object(MongoInt64)#7 (1) {
  ["value"]=&gt;
  string(17) "12345678901234567"
}
12345678901234567
12345678901234567

&lt;/pre&gt;
      &lt;p&gt;The &lt;code&gt;MongoInt32&lt;/code&gt; and &lt;code&gt;MongoInt64&lt;/code&gt; classes implement &lt;code&gt;__toString()&lt;/code&gt; so that their values can be echoed. You can only get their values out as strings. Please be aware that MongoDB is type-sensitive, and will not treat a number contained in a string the same way as a number that's just a number. This script shows this (on a 64-bit platform):&lt;/p&gt;
      &lt;pre&gt;&lt;?php
ini_set('mongo.native_long', 1);

$m = new Mongo();
$c = $m-&gt;selectCollection('test', 'inttest');
$c-&gt;remove(array());

$nr = "12345678901234567";
$c-&gt;insert(array('int64' =&gt; new MongoInt64($nr)));

$r = $c-&gt;findOne(array('int64' =&gt; $nr)); // $nr is a string here
var_dump($r['int64']);
$r = $c-&gt;findOne(array('int64' =&gt; (int) $nr));
var_dump($r['int64']);
?&gt;

&lt;/pre&gt;
      &lt;p&gt;Which shows:&lt;/p&gt;
      &lt;pre&gt;NULL
int(12345678901234567)

&lt;/pre&gt;
      &lt;p&gt;The following tables summarises all the different conversions regarding integers, depending on which settings are enabled:&lt;/p&gt;
      &lt;p&gt;&lt;strong&gt;PHP to MongoDB on 32-bit systems&lt;/strong&gt;:&lt;/p&gt;
      &lt;table&gt;
        &lt;thead&gt;
          &lt;tr&gt;
            &lt;td rowspan="2"&gt;
              &lt;p&gt;From PHP                    &lt;/p&gt;
            &lt;/td&gt;
            &lt;td colspan="2"&gt;
              &lt;p&gt;Stored in Mongo                         &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=0       &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=1      &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;1234567                     &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)       &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;123456789012                &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;FLOAT(123456789012) &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;FLOAT(123456789012)&lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt32("1234567")       &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)       &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt64("123456789012")  &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012)  &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012) &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
      &lt;p&gt;&lt;strong&gt;PHP to MongoDB on 64-bit systems&lt;/strong&gt;:&lt;/p&gt;
      &lt;table&gt;
        &lt;thead&gt;
          &lt;tr&gt;
            &lt;td rowspan="2"&gt;
              &lt;p&gt;From PHP                    &lt;/p&gt;
            &lt;/td&gt;
            &lt;td colspan="2"&gt;
              &lt;p&gt;Stored in Mongo                         &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=0       &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=1      &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;1234567                     &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(1234567)      &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;123456789012                &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;&lt;em&gt;garbage&lt;/em&gt;           &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012) &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt32("1234567")       &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)       &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt64("123456789012")  &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012)  &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012) &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
      &lt;p&gt;&lt;strong&gt;Mongo to PHP on 32-bit systems&lt;/strong&gt;:&lt;/p&gt;
      &lt;table&gt;
        &lt;thead&gt;
          &lt;tr&gt;
            &lt;td rowspan="3"&gt;
              &lt;p&gt;Stored in Mongo   &lt;/p&gt;
            &lt;/td&gt;
            &lt;td colspan="3"&gt;
              &lt;p&gt;Returned to PHP as                                                     &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td colspan="2"&gt;
              &lt;p&gt;long_as_object=0 &lt;/p&gt;
            &lt;/td&gt;
            &lt;td rowspan="2"&gt;
              &lt;p&gt;long_as_object=1         &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=0          &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=1       &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)      &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)           &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)              &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012)&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;float(123456789012)    &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;MongoCursorException&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt64("123456789012")&lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
      &lt;p&gt;&lt;strong&gt;Mongo to PHP on 64-bit systems&lt;/strong&gt;:&lt;/p&gt;
      &lt;table&gt;
        &lt;thead&gt;
          &lt;tr&gt;
            &lt;td rowspan="3"&gt;
              &lt;p&gt;Stored in Mongo   &lt;/p&gt;
            &lt;/td&gt;
            &lt;td colspan="3"&gt;
              &lt;p&gt;Returned to PHP as                                                     &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td colspan="2"&gt;
              &lt;p&gt;long_as_object=0 &lt;/p&gt;
            &lt;/td&gt;
            &lt;td rowspan="2"&gt;
              &lt;p&gt;long_as_object=1         &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=0          &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;native_long=1       &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;INT(1234567)      &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)           &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)        &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(1234567)              &lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
            &lt;td&gt;
              &lt;p&gt;LONG(123456789012)&lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;float(123456789012)    &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;int(123456789012)   &lt;/p&gt;
            &lt;/td&gt;
            &lt;td&gt;
              &lt;p&gt;MongoInt64("123456789012")&lt;/p&gt;
            &lt;/td&gt;
          &lt;/tr&gt;
        &lt;/tbody&gt;
      &lt;/table&gt;
      &lt;p&gt;
        &lt;strong&gt;Conclusion&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;Getting 64-bit support right with MongoDB can be tricky as we've seen. My recommendations would be to use just &lt;code&gt;mongo.native_long=1&lt;/code&gt; if you only deal with 64-bit platforms for your code. In this case, every integer number that you put into MongoDB will also come out as an integer number; with 64-bit integers supported.&lt;/p&gt;
      &lt;p&gt;If you however have to deal with 32-bit platforms (remember, that includes a 64-bit Windows build of PHP) then you can not reliably use just PHP's integer types and you &lt;strong&gt;have&lt;/strong&gt; to use the &lt;code&gt;MongoInt64&lt;/code&gt; class. This comes with the restriction that you have to deal with numbers in strings for initialisation. You also need to be aware that the MongoDB shell regards all numbers as floating point numbers, and that it can not represent 64-bit integer values. Instead they will show up as floating point numbers. Do &lt;strong&gt;not&lt;/strong&gt; attempt to modify those numbers on the shell, as that &lt;a href="http://www.mongodb.org/display/DOCS/mongo%2B-%2BThe%2BInteractive%2BShell#mongo-TheInteractiveShell-Numbers"&gt;could&lt;/a&gt; change the type.&lt;/p&gt;
      &lt;p&gt;So with the script:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$m = new Mongo();
$c = $m-&gt;selectCollection('test', 'inttest');
$c-&gt;remove(array());

$c-&gt;insert(array('int64' =&gt; new MongoInt64("123456789012345678")));

&lt;/pre&gt;
      &lt;p&gt;The MongoDB shell &lt;code&gt;mongo&lt;/code&gt; behaves like:&lt;/p&gt;
      &lt;pre&gt;$ mongo
MongoDB shell version: 1.4.4
url: test
connecting to: test
type "help" for help
&gt; use test
switched to db test
&gt; db.inttest.find()
{ "_id" : ObjectId("4c5ea6d59a14ce1319000000"), "int64" : { "floatApprox" : 123456789012345680, "top" : 28744523, "bottom" : 2788225870 } }

&lt;/pre&gt;
      &lt;p&gt;Of course, when fetching data through a driver that supports 64-bit integers you get the proper result:&lt;/p&gt;
      &lt;pre&gt;ini_set('mongo.long_as_object', 1);
$r = $c-&gt;findOne();
var_dump($r['int64']);
?&gt;

&lt;/pre&gt;
      &lt;p&gt;Which shows:&lt;/p&gt;
      &lt;pre&gt;object(MongoInt64)#7 (1) {
  ["value"]=&gt;
  string(18) "123456789012345678"
}

&lt;/pre&gt;
      &lt;p&gt;The new functionality as outlined in this article is part of the &lt;a href="http://pecl.php.net/package-info.php?package%3Dmongo&amp;amp;version%3D1.0.9"&gt;1.0.9 mongo release&lt;/a&gt; that's available through PECL with &lt;code&gt;pecl install mongo&lt;/code&gt;. Good luck with your 64-bit integers!&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201008091423</guid>
      <pubDate>Mon, 09 Aug 2010 13:23:00 +0000</pubDate>
    </item>
    <item>
      <title>VMWare on Debian Unstable</title>
      <link>http://derickrethans.nl/vmware-debian.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="vmware_on_debian_unstable"/&gt;VMWare on Debian Unstable&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Saturday, August 7th 2010, 16:08 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;In the past week I've been doing some work on the &lt;a href="http://github.com/mongodb/mongo-php-driver"&gt;MongoDB PHP Driver&lt;/a&gt;, and while running the test cases I noticed that there are some issues with it when you run out of disk space. It's sadly hard to reproduce so I set out to create a VMWare image for the MongoDB developers to reproduce this issue.&lt;/p&gt;
      
      
      
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201008071608</guid>
      <pubDate>Sat, 07 Aug 2010 15:08:00 +0000</pubDate>
    </item>
    <item>
      <title>Xdebug 2.1</title>
      <link>http://derickrethans.nl/xdebug-2.1-released.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="xdebug_2_1"/&gt;Xdebug 2.1&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Tuesday, June 29th 2010, 15:17 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;img src="/images/content/xdebug_logo.png" class="right" alt="xdebug_logo.png"/&gt;
      &lt;p&gt;I've just released &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; 2.1. This new release contains all the bug fixes and new features that have been developed over the past three years. It provides full PHP 5.3 support, but it no longer supports PHP versions below 5.1.&lt;/p&gt;
      &lt;p&gt;A description of all the new features follows:&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Error Collection&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;I've added xdebug_start_error_collection(), xdebug_stop_error_collection() and xdebug_get_collected_errors(), which allow you to collect all notices, warnings and error messages that Xdebug generates from PHP's error_reporting functionality so that you can output them at a later point in your script by hand.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Header Setting Interception&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;All functions that set HTTP headers such as with &lt;a href="http://php.net/header"&gt;header()&lt;/a&gt; and &lt;a href="http://php.net/setcookie"&gt;setcookie()&lt;/a&gt; are now intercepted by Xdebug. The intercepted headers are stored internally in an array that can be retrieved by calling the &lt;a href="http://xdebug.org/docs/all_functions#xdebug_get_headers"&gt;xdebug_get_headers()&lt;/a&gt; function. This is very useful in cases where you need to test certain functionality that sets headers somewhere deep in code. This function is also used in &lt;a href="http://ezcomponents.org"&gt;eZ Components'&lt;/a&gt; test suite to &lt;a href="http://svn.ez.no/svn/ezcomponents/trunk/MvcTools/tests/response_writers/http.php"&gt;test&lt;/a&gt; whether the correct HTTP headers are set in the &lt;a href="http://ezcomponents.org/s/MvcTools"&gt;MvcTools&lt;/a&gt; component.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Variable Assignment Tracing&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;The new setting &lt;a href="http://xdebug.org/docs/all_settings#collect_assignments"&gt;xdebug.collect_assignments&lt;/a&gt; allows you to record changes to variables in scripts to &lt;a href="http://xdebug.org/docs/execution_trace"&gt;trace files&lt;/a&gt;.  I've already written more about it in &lt;a href="http://derickrethans.nl/variable-tracing-with-xdebug.html"&gt;Variable tracing with Xdebug&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;"Scream" Support&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;The &lt;a href="http://pecl.php.net/scream"&gt;scream&lt;/a&gt; PECL extension disables the &lt;code&gt;@&lt;/code&gt; (shut-up) operator to actually see all notices, warnings and errors that PHP generates. The scream extension's functionality have been duplicated as Xdebug's &lt;a href="http://xdebug.org/docs/all_settings#scream"&gt;xdebug.scream&lt;/a&gt; php.ini setting. Why disabling the @-operator is a good thing, I've already outlined in &lt;a href="http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html"&gt;Five reasons why the shut-op operator (@) should be avoided&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Additions for Stack Traces&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;All HTML containers generated by Xdebug (error messages, &lt;a href="http://xdebug.org/docs/all_functions#xdebug_var_dump"&gt;xdebug_var_dump()&lt;/a&gt; output) now contain a CSS class for easier styling.&lt;/p&gt;
      &lt;p&gt;The new setting &lt;a href="http://xdebug.org/docs/all_settings#file_link_format"&gt;xdebug.file_link_format&lt;/a&gt; allows you to turn any file/line link in Xdebug's output to be decorated to a link with a specific format.  For example you can set it to &lt;code&gt;txmt://open/?file://%f&amp;line=%l&lt;/code&gt; for opening files directly in Textmate, or &lt;code&gt;gvim://%f@%l&lt;/code&gt; with some shell script for gvim and Firefox.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Remote Debugging&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;The new setting &lt;a href="http://xdebug.org/docs/all_settings#remote_connect_back"&gt;xdebug.remote_connect_back&lt;/a&gt;, contributed by Lucas Nealan and Brian Shire, allows Xdebug to try to make a debugging connection to the IP address from which the browser request came from. This setting is an additional solution for &lt;a href="http://derickrethans.nl/debugging-with-multiple-users.html"&gt;debugging with multiple users&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;The old &lt;code&gt;gdb&lt;/code&gt; and &lt;code&gt;php3&lt;/code&gt; remote debugging engines have been removed.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Overloaded var_dump&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;The newly introduced setting xdebug.overload_var_dump can be used to turn off Xdebug's default behavior of overriding PHP's &lt;a href="http://php.net/var_dump"&gt;var_dump()&lt;/a&gt; function with the &lt;a href="http://xdebug.org/docs/all_functions#xdebug_var_dump"&gt;xdebug_var_dump()&lt;/a&gt; function that uses pretty HTML for formatting a variable structure. It does not stop &lt;a href="http://xdebug.org/docs/all_functions#xdebug_var_dump"&gt;xdebug_var_dump()&lt;/a&gt; from working however.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Donations&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;You can probably imagine that writing and support Xdebug is a time-consuming effort. It's a tool that saves a lot of work during developement of applications, as well while debugging.  If you think Xdebug is valuable for you, perhaps you would like to consider a &lt;a href="http://xdebug.org/donate.php"&gt;donation&lt;/a&gt;. All donations are greatly appreciated and support future development and availablity of Xdebug.&lt;/p&gt;
      &lt;p&gt;If you want to sponsor a (new) feature in Xdebug, feel free to &lt;a href="mailto:derick@xdebug.org"&gt;contact&lt;/a&gt; me as well.&lt;/p&gt;
      &lt;p&gt;
        &lt;strong&gt;Download and Support&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;The new version of Xdebug can be downloaded through the &lt;a href="http://xdebug.org/download.php"&gt;download&lt;/a&gt; page. A list with all changes can be found on the &lt;a href="http://xdebug.org/updates.php#x_2_1_0"&gt;updates&lt;/a&gt; page. Support information can be found on the &lt;a href="http://xdebug.org/support.php"&gt;support&lt;/a&gt; page, and issues and feature requests can be filed in the &lt;a href="http://bugs.xdebug.org"&gt;bug tracker&lt;/a&gt;. Before asking for support, please have a look at the &lt;a href="http://xdebug.org/docs/faq"&gt;FAQ&lt;/a&gt; first.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201006291449</guid>
      <pubDate>Tue, 29 Jun 2010 14:17:00 +0000</pubDate>
    </item>
    <item>
      <title>Yahoo! Search's new front page</title>
      <link>http://derickrethans.nl/yahoo-search-page.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="yahoo_search_s_new_front_page"/&gt;Yahoo! Search's new front page&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Thursday, May 6th 2010, 11:10 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;Yahoo! Search recently changed their front page to include three of "Earth's Biggest Puzzles". As a long time user I find this really obnoxious especially because there doesn't seem to be any way to turn this off. So I decided to do something about it and I wrote a &lt;a href="http://www.greasespot.net/"&gt;Greasemonkey&lt;/a&gt; script to get rid of it again. You can find the script &lt;a href="/files/earthdayremover.user.js"&gt;here&lt;/a&gt;.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201005061110</guid>
      <pubDate>Thu, 06 May 2010 10:10:00 +0000</pubDate>
    </item>
    <item>
      <title>Find my Xdebug download wizard</title>
      <link>http://derickrethans.nl/find-my-xdebug-download-wizard.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="find_my_xdebug_download_wizard"/&gt;Find my Xdebug download wizard&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Monday, May 3rd 2010, 10:00 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;Installing &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; seems to be a problem for some users. The main trouble is for Windows users that don't know which file to download. Over the past few days I've worked on a &lt;a href="http://xdebug.org/find-binary.php"&gt;wizard&lt;/a&gt; that analyses &lt;a href="http://php.net/phpinfo"&gt;phpinfo()'s&lt;/a&gt; output and for Windows users suggests:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;p&gt;which file to download&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;where to put the file&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;which php.ini file to modify, and how&lt;/p&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;For Unix users, it explains:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;p&gt;which source tarball to download&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;how to compile&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;which php.ini file to modify, and how&lt;/p&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;I hope this makes it a bit easier to get going with Xdebug. Next up (hopefully this week) is release candidate 2 for Xdebug 2.1.0.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201005031000</guid>
      <pubDate>Mon, 03 May 2010 09:00:00 +0000</pubDate>
    </item>
    <item>
      <title>PHP and Ordnance Survey Mapping</title>
      <link>http://derickrethans.nl/php-mapping.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="php_and_ordnance_survey_mapping"/&gt;PHP and Ordnance Survey Mapping&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Tuesday, April 27th 2010, 14:27 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;About a month ago, &lt;a href="http://www.ordnancesurvey.co.uk/"&gt;Ordnance Survey&lt;/a&gt; &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/media/news/2010/April/OpenData.html"&gt;opened&lt;/a&gt; up some of their data for public consumption under a brand called &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/opendata/"&gt;OpenData&lt;/a&gt;. The data is &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/opendata/licence/docs/licence.pdf"&gt;licenced&lt;/a&gt; under a "Creative Commons Attribute"-like license. One of the data sets they provide is &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/products/code-point-open/"&gt;Code-Point Open&lt;/a&gt; and provides a dataset "that contains postcode units, each of which have a precise geographical location". I've always been a bit of a map-geek, and have always geotagged my &lt;a href="http://www.flickr.com/photos/derickrethans/map"&gt;pictures&lt;/a&gt; and some of my &lt;a href="http://twitter.com/derickr"&gt;tweets&lt;/a&gt;. So I was wondering what cool thing I could do with this newly released data.  I decided to map all the postcodes onto the UK map where more postcodes for a specific place would create a "lighter" colour. Each postcode has on average about 15 addresses, so in more densely populated areas you have more "postcodes-per-area". Doing this wasn't very difficult and it resulted in the following map:&lt;/p&gt;
      &lt;img src="/images/content/postcode-uk-scaled.jpg" alt="postcode-uk-scaled.jpg"/&gt;
      &lt;p&gt;You can very clearly see the more densely populated areas such as London.&lt;/p&gt;
      &lt;p&gt;This generated postcode-density map I wanted to overlay on a real map, such as OpenStreetMap provides. When I tried to align the image that I generated with the OSM map, I ended up with this:&lt;/p&gt;
      &lt;img src="/images/content/uk-osm-postcode-overlay.jpg" alt="uk-osm-postcode-overlay.jpg"/&gt;
      &lt;p&gt;Obviously, the maps don't align. In order to fix this, I ended up learning a lot more about map projections.&lt;/p&gt;
      &lt;p&gt;The &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/products/code-point-open/"&gt;Code-Point Open&lt;/a&gt; data uses the UK's &lt;a href="http://en.wikipedia.org/wiki/British_national_grid_reference_system#Grid_letters"&gt;National Grid&lt;/a&gt; to store location data in. The National Grid consists of 100*100 km squares that are then further subdivided into smaller squares creating grid references such as &lt;em&gt;TQ3012780512&lt;/em&gt;, or the numerical version &lt;em&gt;530128 180512&lt;/em&gt;. &lt;em&gt;TQ&lt;/em&gt; translates into the "hundred thousands" of the &lt;em&gt;Eastings&lt;/em&gt; and &lt;em&gt;Northings&lt;/em&gt; according to the grid that you can see &lt;a href="http://en.wikipedia.org/wiki/File:National_Grid_for_Great_Britain_with_central_meridian.gif"&gt;here&lt;/a&gt;. In this case, it specifies a point 530 128 meters East and 180 512 meters North of the origin.  (If you work it out, you'll end up in London).&lt;/p&gt;
      &lt;p&gt;&lt;a href="http://www.openstreetmap.org/"&gt;OpenStreetMap&lt;/a&gt; uses a &lt;a href="http://en.wikipedia.org/wiki/Mercator_projection"&gt;Mercator&lt;/a&gt; projection to visualize maps. The Mercator projection is a cylindrical map projection, and it distorts the size and shape of large objects, as the scale increases from the Equator to the poles. Therefore it only works from about 85°N to 85°S (why it is 85° only be came clear after doing all the maths for it). Google Maps uses the same projection.&lt;/p&gt;
      &lt;p&gt;There were a few challenges plotting the &lt;a href="http://www.ordnancesurvey.co.uk/oswebsite/products/code-point-open/"&gt;Code-Point Open&lt;/a&gt; data on an OpenStreetMap map:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;p&gt;The National Grid coordinates need to be converted to Latitude/Longitude pairs&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;Latitude/Longitude pairs need to be mapped to pixels to align with the Mercator projection of OpenStreetMap maps.&lt;/p&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;For &lt;strong&gt;converting National Grid&lt;/strong&gt; references to Latitude/Longitude pairs I found some &lt;a href="http://www.movable-type.co.uk/scripts/latlong-gridref.html"&gt;JavaScript code&lt;/a&gt;. I converted this code to PHP and to verify whether my code was working properly, I used &lt;a href="http://www.fieldenmaps.info/cconv/cconv_gb.html"&gt;this site&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;&lt;strong&gt;Converting Latitude/Longitude&lt;/strong&gt; pairs to the pixel coordinates of OSM required a bit of maths. OSM provides maps in different zoom levels, from &lt;a href="http://www.openstreetmap.org/?lat%3D0&amp;amp;lon%3D0&amp;amp;zoom%3D2&amp;amp;layers%3DB000FTFT"&gt;2&lt;/a&gt; to &lt;a href="http://www.openstreetmap.org/?lat%3D51.500834&amp;amp;lon%3D-0.142455&amp;amp;zoom%3D17&amp;amp;layers%3DB000FTFT"&gt;17&lt;/a&gt;. Each zoom level having twice the amount of pixels horizontally and vertically.  Zoom level 2 has 4 times 4 tiles, where each tile is 256*256 pixels. At zoom level two, the whole world fits into 1024*1024 pixels. The number of pixels for each axis for a specific zoom-level can be calculated by:&lt;/p&gt;
      &lt;pre&gt;pow(2^zoom) * 256

&lt;/pre&gt;
      &lt;p&gt;For a zoom level of 7 that makes 16384 pixels in each direction. To convert a longitude (in the range -180° to 180°) we can simply apply:&lt;/p&gt;
      &lt;pre&gt;x = ((lon + 180) / 360) * (pow(2^zoom) * 256)

&lt;/pre&gt;
      &lt;p&gt;For a Longitude of 0.003117° E at zoom-level 13 that turns out to be pixel 1048594.&lt;/p&gt;
      &lt;p&gt;Longitude conversions are more difficult due to the Mercator projection itself. To convert we apply:&lt;/p&gt;
      &lt;pre&gt;y = ((atanh(sin(deg2rad(-lat))) / π) + 1) * (pow(2^(zoom-1)))

&lt;/pre&gt;
      &lt;p&gt;For a Latitude of 51.502817° N at zoom-level 13 that turns out to be pixel 697399.&lt;/p&gt;
      &lt;p&gt;Creating an image for the whole world at zoom level 13 is impractical as it is 2097152*2097152 pixels and downloading all the 67 million tiles for this zoom level is probably not liked by the OSM people either. So instead we take a cut out for a specific area only. For the UK (61.37°N -9.49° W, 49.76°N +3.63°E) at zoom level 7 we end up with a 1536x2048 map with the North-Western pixel being 15360,9216. On this map, we can draw the latitudes and longitudes as well as the National Grid lines (full image is on &lt;a href="http://farm4.static.flickr.com/3001/4557130189_af995cab6b_o.png"&gt;flickr&lt;/a&gt;):&lt;/p&gt;
      &lt;img src="/images/content/uk-osm-lines-crop.jpg" alt="uk-osm-lines-crop.jpg"/&gt;
      &lt;p&gt;The only thing left to do now, is to map the postcode density information to the map. I picked zoom level 6 for this, and the result is (after cropping it to 640 pixels width):&lt;/p&gt;
      &lt;img src="/images/content/uk-osm-postcode.jpg" alt="uk-osm-postcode.jpg"/&gt;
      &lt;p&gt;As you can see, this is perfect fit to the outlines of the country. But unfortunately, when we look very closely at the plotted map data, for example for the &lt;em&gt;NW10 3&lt;/em&gt; postcodes, we notice that the mapping is slightly off. The blue dots are what we plotted, and the red dots are what the locations &lt;strong&gt;should&lt;/strong&gt; have been:&lt;/p&gt;
      &lt;img src="/images/content/uk-osm-nw103-1.png" alt="uk-osm-nw103-1.png"/&gt;
      &lt;p&gt;The reason for this is that when we converted the National Grid locations to Latitude/Longitude pairs to plot on the OSM maps, I forgot to take into account the different &lt;a href="http://en.wikipedia.org/wiki/Datum_%2528geodesy%2529"&gt;Datums&lt;/a&gt; that are used in the projections. The Earth is not a perfect sphere, and an approximation of the ellipsoid of the whole Earth is not necessarily the best fitting for a specific area such as the UK. Therefore, the National Grid uses the &lt;a href="http://en.wikipedia.org/wiki/OSGB36#Datum_shift_between_OSGB_36_and_WGS_84"&gt;OSGB36&lt;/a&gt; Datum which fits more closely to the UK, where as OpenStreetMap uses the WGS84 Datum that is also used by GPS. The &lt;a href="http://osi.ie/"&gt;Ordnance Survey Ireland&lt;/a&gt; has a more thorough &lt;a href="http://www.osi.ie/GetAttachment.aspx?id%3Db2bd07a6-858e-4eb1-9d09-25917f0c713a"&gt;explanation&lt;/a&gt; on their site. As you can see above, using the wrong Datum can mean locations can be off. In our example about 100 meters. Converting between different Datums is possible, albeit processor intensive.&lt;/p&gt;
      &lt;p&gt;After I figured out all the maths for this, the only problem that remains that implementing those algorithms in PHP is show—calculating all the positions from the 1.6 million postcode locations takes up to 10 minutes. This is why I am not presenting any code yet. I am planning to implement all the necessary calculations in a &lt;a href="http://derickrethans.nl/available-for-php-extension-writing.html"&gt;PHP extension&lt;/a&gt; to speed up the calculations&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201004271427</guid>
      <pubDate>Tue, 27 Apr 2010 13:27:00 +0000</pubDate>
    </item>
    <item>
      <title>VLD released</title>
      <link>http://derickrethans.nl/vld-released.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="vld_released"/&gt;VLD released&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Monday, April 12th 2010, 21:57 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;I just released a new version of &lt;a href="http://derickrethans.nl/projects.html#vld"&gt;VLD&lt;/a&gt; through &lt;a href="http://pecl.php.net/package/vld"&gt;PECL&lt;/a&gt;. This release features the path analytics code that I've outlined in an &lt;a href="http://derickrethans.nl/more-source-analysis-with-vld.html"&gt;earlier article&lt;/a&gt;. There are also a few fixes for PHP's current trunk, as well as the possibility to format output slightly like a CSV file. That feature was used to make &lt;a href="http://www.zapt.info/opcodes.html"&gt;this&lt;/a&gt; documentation of opcodes.&lt;/p&gt;
      &lt;p&gt;The path analysis algorithm that &lt;a href="http://derickrethans.nl/projects.html#vld"&gt;VLD&lt;/a&gt; now has, can possibly also be used to get path/branch coverage working within &lt;a href="http://xdebug.org"&gt;Xdebug's&lt;/a&gt; code-coverage framework. This is however not a minor task.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201004122157</guid>
      <pubDate>Mon, 12 Apr 2010 20:57:00 +0000</pubDate>
    </item>
    <item>
      <title>Xdebug 2.1.0 RC1 released</title>
      <link>http://derickrethans.nl/xdebug-2.1.0rc1-released.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="xdebug_2_1_0_rc1_released"/&gt;Xdebug 2.1.0 RC1 released&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; Schiphol, Netherlands&lt;/div&gt;
        &lt;div class="date"&gt;Tuesday, April 6th 2010, 15:41 CEST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;As earlier announced in my April Fools' &lt;a href="http://derickrethans.nl/xdebug-will-cost-money.html"&gt;announcement&lt;/a&gt; and on Xdebug's &lt;a href="http://twitter.com/xdebug/status/11687180290"&gt;twitter&lt;/a&gt; feed, I'm now releasing &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; 2.1.0RC1. This is the first Release Candidate and it addresses a number of &lt;a href="http://xdebug.org/updates.php#x_2_1_0rc1"&gt;issues&lt;/a&gt; found in the latest beta. As I usually do in release announcements, I will also be introducing a new feature in Xdebug 2.1 in this one.&lt;/p&gt;
      &lt;p&gt;In an &lt;a href="http://derickrethans.nl/five-reasons-why-the-shutop-operator-should-be-avoided.html"&gt;article&lt;/a&gt; that I wrote a few months ago, I illustrated a few different reasons on why the shut-op operator (&lt;code&gt;@&lt;/code&gt;) should be avoided. Although there are a few cases where it simple can not be avoided if you want to write notice-free code, the main reason why this operator should be avoided, is because it makes debugging quite a bit more difficult if errors are hidden.&lt;/p&gt;
      &lt;p&gt;Xdebug is a debugging aid to make debugging easier. So from version 2.1.0 there is a new configuration setting — &lt;code&gt;xdebug.scream&lt;/code&gt; — that simply disables the effects of the &lt;code&gt;@&lt;/code&gt; operator. That means that all errors will be shown, of course, still listening to the &lt;code&gt;error_reporting&lt;/code&gt; and &lt;code&gt;display_errors&lt;/code&gt; settings. This functionality is not a novel thing, and the idea was lifted from the PECL &lt;a href="http://pecl.php.net/scream"&gt;scream&lt;/a&gt; package. However, I think this functionality fits in very well with all the other things that Xdebug has to offer.&lt;/p&gt;
      &lt;p&gt;Just to mention it once more, I have no intention of making Xdebug closed source. I spend a considerable amount of time in adding new features and addressing issues, so I would appreciate it that if consider a &lt;a href="http://xdebug.org/donate.php"&gt;donation&lt;/a&gt; in case Xdebug has saved you time and effort in debugging your application. If you have comments or suggestions to improve Xdebug, please write to the &lt;a href="http://xdebug.org/support.php#list"&gt;mailinglist&lt;/a&gt;.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201004061541</guid>
      <pubDate>Tue, 06 Apr 2010 13:41:00 +0000</pubDate>
    </item>
    <item>
      <title>First release of the D-Bus extension</title>
      <link>http://derickrethans.nl/dbus-extension-released.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="first_release_of_the_d-bus_extension"/&gt;First release of the D-Bus extension&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Tuesday, April 6th 2010, 10:33 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;A few days ago I made the first beta release of the &lt;a href="http://pecl.php.net/package/dbus"&gt;D-Bus extension&lt;/a&gt; that I have been working on for a while. &lt;a href="http://www.freedesktop.org/wiki/Software/dbus"&gt;D-Bus&lt;/a&gt; is a message bus system, a simple way for applications to talk to one another. I started working on this because my cellphone, an OpenMoko &lt;a href="http://www.openmoko.com/freerunner.html"&gt;FreeRunner&lt;/a&gt;. This cellphone (or rather, a mobile Linux computing device) implements &lt;a href="http://www.freesmartphone.org/"&gt;freesmartphone.org&lt;/a&gt; APIs to talk to all the hardware that is available on the device. This includes GSM and SIM card interfaces, but also GPS, Audio and PIM services.&lt;/p&gt;
      &lt;p&gt;However, many other applications on the Linux desktop speak D-Bus. This includes system services such as the notification daemon, the screen saver and hardware plug-in detection as well as desktop applications such as &lt;a href="http://www.pidgin.im/"&gt;Pidgin&lt;/a&gt; and &lt;a href="http://live.gnome.org/Empathya"&gt;Empathy&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;I've given a &lt;a href="http://derickrethans.nl/talks/dbus-london2010.pdf"&gt;presentation&lt;/a&gt; on the extension at the &lt;a href="http://www.phpconference.co.uk/"&gt;PHP London conference&lt;/a&gt; earlier this year, and will also be speaking on this subject as part of the "PHP Inside" and "PHP on the D-Bus" talks at &lt;a href="http://tek.phparch.com/schedule/"&gt;Tek-X&lt;/a&gt; (Chicago, May 18-21), &lt;a href="http://it-republik.de/php/phpconference2010se/"&gt;International PHP Conference Spring&lt;/a&gt; (Berlin, May 30-June 2) and the &lt;a href="http://phpconference.nl/"&gt;Dutch PHP Conference&lt;/a&gt; (June 10-12).&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201004060920</guid>
      <pubDate>Tue, 06 Apr 2010 09:33:00 +0000</pubDate>
    </item>
    <item>
      <title>Xdebug no longer Open Source</title>
      <link>http://derickrethans.nl/xdebug-will-cost-money.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="xdebug_no_longer_open_source"/&gt;Xdebug no longer Open Source&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Thursday, April 1st 2010, 10:19 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;
        &lt;strong&gt;This was obviously an April Fools' joke, Xdebug will continue to stay Open Source and free of charge.&lt;/strong&gt;
      &lt;/p&gt;
      &lt;p&gt;Later today I will be releasing the first Release Candidate of Xdebug 2.1. With regret I have to announce that from this release, I will no longer provide Xdebug as an open source debugger extension. I've noticed that there are other projects making money of Xdebug's success while I only receive &lt;a href="http://xdebug.org/donate.php"&gt;donations&lt;/a&gt; from a group of awesome supporters.&lt;/p&gt;
      &lt;p&gt;Xdebug will continue to be available for benefactors on a limited number of platforms that I have access to (Linux 32/64bit and Windows). Please refer to the &lt;a href="http://derickrethans.nl/files/dump/faq.html"&gt;FAQ&lt;/a&gt; for further information.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201004011019</guid>
      <pubDate>Thu, 01 Apr 2010 09:19:00 +0000</pubDate>
    </item>
    <item>
      <title>Storing Date/Times in Databases</title>
      <link>http://derickrethans.nl/storing-date-time-in-database.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="storing_date_times_in_databases"/&gt;Storing Date/Times in Databases&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Monday, March 29th 2010, 16:47 BST&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;After my talk during &lt;a href="http://confoo.ca/en"&gt;ConFoo&lt;/a&gt; on &lt;a href="http://confoo.ca/en/2010/session/advanced-date-time-handling-with-php"&gt;Advanced Date/Time Handling&lt;/a&gt; I received a question about whether the UTC-offset, together with the date/time in years, months, days, hours, minutes and seconds, was enough for storing a date/time in a database and still being able to do calculations with this. The answer to this question was no, but it lead to an even more interesting discussion about what &lt;em&gt;would&lt;/em&gt; be enough to store an accurate date/time in a database.&lt;/p&gt;
      &lt;p&gt;Firstly let me explain why storing a UTC offset is not adequate at all for doing any sort of calculations. Right now (March 25th, 2010), Montreal is on the same time as Santiago (in Chile) with both a UTC offset of -4 hours. This means that for the same date/time (&lt;code&gt;2010-03-25
19:03&lt;/code&gt;) the same timestamp is generated (&lt;code&gt;1269558180&lt;/code&gt;). However if we want to add eight months (&lt;code&gt;2010-11-25 19:03&lt;/code&gt;) to the current time for each of those locations then the timestamps &lt;em&gt;should&lt;/em&gt; be different — &lt;code&gt;1290729780&lt;/code&gt; for Montreal and &lt;code&gt;1290722580&lt;/code&gt; for Santiago. It turns out that &lt;em&gt;neither&lt;/em&gt; of them is exactly a full 24 hour difference from &lt;code&gt;2010-03-25 19:03&lt;/code&gt; as is shown the following script:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$s = '2010-03-25 19:03';
$montrealNow = date_create( "{$s} America/Montreal" )-&gt;format( 'U' );
$santiagoNow = date_create( "{$s} America/Santiago" )-&gt;format( 'U' );
$s = '2010-11-25 19:03';
$montrealThen = date_create( "{$s} America/Montreal" )-&gt;format( 'U' );
$santiagoThen = date_create( "{$s} America/Santiago" )-&gt;format( 'U' );

$hour = 60 * 60;
$day = 24 * $hour;

echo "Montreal:\n",
    $montrealNow, " - ",
    $montrealThen, "\n",
    ( ( $montrealThen - $montrealNow ) % $day ) / $hour, "\n\n";

echo "Santiago:\n",
    $santiagoNow, " - ",
    $santiagoThen, "\n",
    ( ( $santiagoThen - $santiagoNow ) % $day ) / $hour, "\n\n";

?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output:&lt;/p&gt;
      &lt;pre&gt;Montreal:
1269558180 - 1290729780
1

Santiago:
1269558180 - 1290722580
23

&lt;/pre&gt;
      &lt;p&gt;From this we see that Montreal has an extra hour and Santiago has an hour less. This is because Montreal changed from Daylight Savings Time to normal time and Santiago, being on the southern hemisphere, moved from normal time to Daylight Savings time.&lt;/p&gt;
      &lt;p&gt;Now if we had only the timestamp (&lt;code&gt;1269558180&lt;/code&gt;) and the UTC-offset, the only thing we could do would be to advance a specific number of days. In this case, there are 245 days, which makes (&lt;code&gt;245 * 24 * 60 * 60 =&lt;/code&gt; ) &lt;code&gt;21168000&lt;/code&gt; seconds. If we add this to the original timestamp, we end up at &lt;code&gt;1290726180&lt;/code&gt; which corresponds to &lt;code&gt;2010-11-25 18:03&lt;/code&gt; Montreal time, or &lt;code&gt;2010-11-25 20:03&lt;/code&gt; Santiago time. Neither of them being the correct &lt;code&gt;2010-11-25 19:03&lt;/code&gt;. Because from the UTC offset of 4 hours we don't know whether we're in Montreal or Santiago, we can conclude that with just this UTC offset and the original timestamp we can't calculate the timestamp of something that's 8 months in the future. Storing the UTC-offset can not change this fact either.&lt;/p&gt;
      &lt;p&gt;In order to to proper calculations, you need to keep information about the timezone itself. In PHP timezones are identified with identifiers such as &lt;code&gt;America/Montreal&lt;/code&gt;. If we store those alongside the timestamps, we can do the proper calculations. The following example demonstrates that:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$timestamp = 1269558180;
$tzid      = 'America/Montreal';

$d = new DateTime( "@$timestamp" );
$d-&gt;setTimeZone( new DateTimeZone( $tzid ) );
$d-&gt;modify( '+8 months' );

echo $d-&gt;format( 'Y-m-d H:i' ), "\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output: &lt;code&gt;2010-11-25 19:03&lt;/code&gt;.&lt;/p&gt;
      &lt;p&gt;This seems to work, but unfortunately, even the approach of storing the timestamp and timezone identifier is not going to work correctly under certain circumstances. In order to find out why, we have to go back to January this year.&lt;/p&gt;
      &lt;p&gt;Imagine that in January this year—January 15th to be precise—we run the following script to determine the timestamp of a date/time two months in the future:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$tz = 'America/Santiago';
$ts = date_create( "2010-01-15 10:41 $tz" )-&gt;format( 'U' );

$d = new DateTime( "@$ts" );
$d-&gt;setTimeZone( new DateTimeZone( $tz ) );
$d-&gt;modify( '+2 months' );

echo $d-&gt;format( 'U Y-m-d H:i' ), "\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;This returns the timestamp &lt;code&gt;1268664060&lt;/code&gt; for the date/time &lt;code&gt;2010-03-15
10:41:00&lt;/code&gt;.&lt;/p&gt;
      &lt;p&gt;Now skip forwards to the current date and time. If we used this calculated timestamp and the timezone identifier &lt;code&gt;America/Santiago&lt;/code&gt; today to generate a date/time string, we would however get a different output. The following example shows this:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$tz = 'America/Santiago';
$d = date_create( "@1268664060" );
$d-&gt;setTimeZone( new DateTimeZone( $tz ) );

echo $d-&gt;format( 'Y-m-d H:i:s' ), "\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output: &lt;code&gt;2010-03-15 11:41:00&lt;/code&gt; (and not &lt;code&gt;2010-03-15
10:41:00&lt;/code&gt;).&lt;/p&gt;
      &lt;p&gt;The difference in output is not a bug, but is caused because some countries change Daylight Savings Time rules quite frequently. In this case Chile decided (on March 4th) that instead of going forwards to DST at midnight March 14th, they will delay that to April 4th. When we ran the code on January 15th, the rules still thought that March 15th would already be on normal time again, outside of DST. But running the code now, with the updated rule set, we find that DST is still in effect until April 4th. The following example shows the transitions from/to DST for Santiago in 2010:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$tzid = "America/Santiago";

$tz = new DateTimeZone( $tzid );
$transitions = $tz-&gt;getTransitions(
    strtotime( '2010-01-01 00:00 UTC' ),
    strtotime( '2010-12-31 00:00 UTC' )
);

foreach ( $transitions as $t )
{
    echo $t['time'], ' ', $t['offset'] / 3600, ' ', $t['abbr'], "\n";
}
?&gt;

&lt;/pre&gt;
      &lt;p&gt;If we run this script with PHP 5.3.1 or 5.3.2—which still have the old incorrect rule set—the output is:&lt;/p&gt;
      &lt;pre&gt;2010-01-01T00:00:00+0000 -3 CLST
2010-03-14T03:00:00+0000 -4 CLT
2010-10-10T04:00:00+0000 -3 CLST

&lt;/pre&gt;
      &lt;p&gt;In the SVN repository, the rule set has been updated, so snapshots of PHP 5.3-dev have the correct rules and the script will show:&lt;/p&gt;
      &lt;pre&gt;2010-01-01T00:00:00+0000 -3 CLST
2010-04-04T03:00:00+0000 -4 CLT
2010-10-10T04:00:00+0000 -3 CLST

&lt;/pre&gt;
      &lt;p&gt;This leads to the conclusion that storing timestamps and timezone identifiers is not good enough either, unless you want an &lt;em&gt;exact&lt;/em&gt; point in time, as opposed to the more expected date/time in a location. So how &lt;em&gt;should&lt;/em&gt; you store the latter then? Basically, in the same way that DateTime objects are serialized in PHP 5.3. Let us imagine again, that the following code is run on January 15th again:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$tzid = 'America/Santiago';
$d = new DateTime( "2010-01-15 10:41 $tzid" );
$d-&gt;modify( '+2 months' );
$s = $d-&gt;format( 'Y-m-d H:i:s' );
$ts = $d-&gt;format( 'U' );
echo "$s (ts=$ts)\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output &lt;code&gt;2010-03-15 10:41:00 (ts=1268664060)&lt;/code&gt;. The next example is run with a recent rule set (such as in PHP SVN) today:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$tzid = 'America/Santiago';
$d = new DateTime( "$s $tzid" );
$s = $d-&gt;format( 'Y-m-d H:i:s' );
$ts = $d-&gt;format( 'U' );
echo "$s (ts=$ts)\n";
?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output &lt;code&gt;2010-03-15 10:41:00 (ts=1268660460)&lt;/code&gt;. As you can see, now the date/time itself is correct, although there is a different timestamp. PHP's DateTime serialisation does something similar:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
$d = new DateTime();
$d-&gt;setTimeZone( new DateTimeZone( 'America/Santiago' ) );
var_dump( $d );
?&gt;

&lt;/pre&gt;
      &lt;p&gt;which gives the output:&lt;/p&gt;
      &lt;pre&gt;object(DateTime)#1 (3) {
  ["date"]=&gt;
  string(19) "2010-03-29 11:32:08"
  ["timezone_type"]=&gt;
  int(3)
  ["timezone"]=&gt;
  string(16) "America/Santiago"
}

&lt;/pre&gt;
      &lt;p&gt;For things to work correctly, you need to have an up-to-date rule set. PHP versions are not released as often as the timezonedb (sometimes more than 20 times a year) and to address this issue you can install the pecl extension &lt;a href="http://pecl.php.net/package/timezonedb"&gt;timezonedb&lt;/a&gt; with &lt;code&gt;pecl install timezonedb&lt;/code&gt;.&lt;/p&gt;
      &lt;p&gt;To store information in a database, I would use a &lt;code&gt;char&lt;/code&gt; column-type to store the whole &lt;code&gt;America/Santiago&lt;/code&gt; timezone identifier and another &lt;code&gt;char&lt;/code&gt; column-type to store the date/time (in the &lt;code&gt;yyyy-mm-dd
hh:ii:ss&lt;/code&gt; format).  Alternatively, you can pick a 'datetime' column-type, as long as that type &lt;strong&gt;ignores&lt;/strong&gt; timezones altogether. For MySQL that is the &lt;code&gt;DATETIME&lt;/code&gt; column-type, and for PostgreSQL the &lt;code&gt;TIMESTAMP&lt;/code&gt; or &lt;code&gt;TIMESTAMP WITHOUT TIME ZONE&lt;/code&gt; column-types.&lt;/p&gt;
      &lt;p&gt;Databases rarely handle timezones, daylight savings time and rule changes correctly, so avoid the database specific functionality all together. Using either a &lt;code&gt;char&lt;/code&gt; or a timezone-less 'datetime' column-type would still allow you to sort and by using a 'datetime' column-type you can even do calculations.&lt;/p&gt;
      &lt;p&gt;Happy summer time!&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201003291647</guid>
      <pubDate>Mon, 29 Mar 2010 15:47:00 +0000</pubDate>
    </item>
    <item>
      <title>Available for PHP Extension Writing</title>
      <link>http://derickrethans.nl/available-for-php-extension-writing.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="available_for_php_extension_writing"/&gt;Available for PHP Extension Writing&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Monday, March 15th 2010, 12:28 GMT&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;Slightly more than a month ago I left my job as team-lead of &lt;a href="http://ezcomponents.org"&gt;eZ Components&lt;/a&gt; at &lt;a href="http://ez.no"&gt;eZ Systems&lt;/a&gt; behind, to focus on something new. During the past month I've been contemplating about what to do next and realized that I do not want to take on a new full-time position right away.  Instead I will be available to work on (custom) PHP extensions and internals related issues. Extensions are a great way around PHP's limitations and performance issues.&lt;/p&gt;
      &lt;p&gt;As first project I am working on a "&lt;a href="http://svn.xdebug.org/quickhash/trunk"&gt;QuickHash&lt;/a&gt;" extension for &lt;a href="http://www.stumbleupon.com/"&gt;StumbleUpon&lt;/a&gt;. This extension circumvents PHP's hefty memory (and performance) overhead by providing more specific data structures. The extension currently implements integer sets and integer to integer hashes. I am now adding integer to string hashes and string to integer hashes. The QuickHash extension will be released under the PHP Licence and I will dedicate another post to it later.&lt;/p&gt;
      &lt;p&gt;If, like &lt;a href="http://www.stumbleupon.com/"&gt;StumbleUpon&lt;/a&gt;, you are also interested in having work done on PHP or a specific extensions feel free to &lt;a href="/who.html"&gt;contact&lt;/a&gt; me. I'd be happy to discuss things with you.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201003151228</guid>
      <pubDate>Mon, 15 Mar 2010 12:28:00 +0000</pubDate>
    </item>
    <item>
      <title>Xdebug 2.1.0beta3 released</title>
      <link>http://derickrethans.nl/xdebug-210beta3.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="xdebug_2_1_0beta3_released"/&gt;Xdebug 2.1.0beta3 released&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Saturday, February 27th 2010, 23:57 GMT&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;I've just released Xdebug 2.1.0beta3 which includes a few crash bugs as well as the issue that headers sent from PHP scripts are not actually set.&lt;/p&gt;
      &lt;p&gt;You can find the full changelog &lt;a href="http://xdebug.org/updates.php#x_2_1_0beta3"&gt;here&lt;/a&gt; and get the latest version from the &lt;a href="http://xdebug.org/download.php"&gt;download page&lt;/a&gt;.&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201002272352</guid>
      <pubDate>Sat, 27 Feb 2010 23:57:00 +0000</pubDate>
    </item>
    <item>
      <title>More source analysis with VLD</title>
      <link>http://derickrethans.nl/more-source-analysis-with-vld.html</link>
      <description>&lt;div class="article"&gt;
  &lt;div class="body"&gt;
    &lt;div class="articleListItem"&gt;
      &lt;h1&gt;&lt;a name="more_source_analysis_with_vld"/&gt;More source analysis with VLD&lt;/h1&gt;
      &lt;dl class="head"/&gt;
      &lt;div class="articleMetaData"&gt;
        &lt;div class="location"&gt; London, UK&lt;/div&gt;
        &lt;div class="date"&gt;Friday, February 19th 2010, 11:27 GMT&lt;/div&gt;
      &lt;/div&gt;
      &lt;p&gt;&lt;a href="http://derickrethans.nl/projects.html#vld"&gt;VLD&lt;/a&gt; is a tool that I started working on years ago to visualise the opcode arrays in PHP. Opcode arrays are what PHP's compiler generates from your source code and can be compared to assembler code that is generated by a C compiler. Instead of it being directly executed by the CPU, it is instead executed by PHP's interpreter.&lt;/p&gt;
      &lt;p&gt;Over the years I've been adding some functionality, also aided by &lt;a href="http://ilia.ws"&gt;Ilia&lt;/a&gt; and some others, to show more information. For example Ilia has added a more verbose dumping format for opcodes (through the &lt;code&gt;vld.verbosity&lt;/code&gt; setting) whereas I have added routines to find out which ops in oparrays can never be reached. A very simple example of the latter is shown here:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
function test()
{
        echo "Hello!\n";
        return true;

        echo "This will not be executed.\n";
}
?&gt;

&lt;/pre&gt;
      &lt;p&gt;If we run the above through VLD with &lt;code&gt;php -dvld.active=1 test.php&lt;/code&gt;, you'll see the following output (I removed the part about the script body itself):&lt;/p&gt;
      &lt;pre&gt;Function test:
filename:       /tmp/test1.php
function name:  test
number of ops:  9
compiled vars:  none
line     # *  op           fetch  ext  return  operands
---------------------------------------------------------
   2     0  &gt;   EXT_NOP
   4     1      EXT_STMT
         2      ECHO                           'Hello%21%0A'
   5     3      EXT_STMT
         4    &gt; RETURN                         true
   7     5*     EXT_STMT
         6*     ECHO                           'This+will+not+be+executed.%0A'
   8     7*     EXT_STMT
         8*   &gt; RETURN                         null

End of function test.

&lt;/pre&gt;
      &lt;p&gt;Every opcode that has a &lt;code&gt;*&lt;/code&gt; after the number (like in &lt;code&gt;5*&lt;/code&gt;) is code that can not be reached, and can possibly be eliminated from the oparrays in an optimiser.&lt;/p&gt;
      &lt;p&gt;The dead code analysis routines have also made their way into &lt;a href="http://xdebug.org"&gt;Xdebug&lt;/a&gt; which uses them for the &lt;a href="http://xdebug.org/docs/code_coverage"&gt;code coverage&lt;/a&gt; functionality to highlight dead code. This mostly makes sense if you are running your code coverage together with unit tests such as you can do with &lt;a href="http://www.phpunit.de"&gt;PHPUnit&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;Recently I've been working on some new functionality to visualise all the code &lt;em&gt;paths&lt;/em&gt; that make up each function. These new routines sit on top of the routines that do dead code analysis. Every branch instruction (such as &lt;code&gt;if&lt;/code&gt;, but also &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;foreach&lt;/code&gt;) is analysed and a list of branches is created. Each branch contains information about the line on which the branch starts, the starting and ending opcode numbers that belong to the branch, as well as to which other branches this branch can jump to. There can be either no linked branches (when for example a &lt;code&gt;return&lt;/code&gt; or &lt;code&gt;throw&lt;/code&gt; statement is found), one linked branch (for an unconditional jump) or two linked branches (on a branch instruction).  However, you need to be aware that internally, PHP's opcode don't always reflect the &lt;em&gt;source code&lt;/em&gt; exactly.&lt;/p&gt;
      &lt;p&gt;Once all the branches and their links are found, another algorithm runs to figure out which paths can be created out of all the branches. It is best to illustrate this with an example. So let us look at the following script:&lt;/p&gt;
      &lt;pre&gt;&lt;?php
function test()
{
        for( $i = 0; $i &lt; 10; $i++ )
        {
                if ( $i &lt; 5 )
                {
                        echo "-";
                }
                else
                {
                        echo "+";
                }
        }
        echo "\n";
}
?&gt;

&lt;/pre&gt;
      &lt;p&gt;In this script we have a &lt;code&gt;for&lt;/code&gt;-loop with a nested &lt;code&gt;if&lt;/code&gt; construct. When we run this script through VLD (with &lt;code&gt;php -dvld.verbosity=0 -dvld.dump_paths=1
-dvld.active=1 test2.php&lt;/code&gt;) we get the following output (again, only the &lt;code&gt;test()&lt;/code&gt; function and with some white space modifications):&lt;/p&gt;
      &lt;pre&gt;Function test:
filename:       /tmp/test2.php
function name:  test
number of ops:  22
compiled vars:  !0 = $i
line     # *  op             fetch  ext  return  operands
-----------------------------------------------------------
   2     0  &gt;   EXT_NOP
   4     1      EXT_STMT
         2      ASSIGN                             !0, 0
         3  &gt;   IS_SMALLER                 ~1      !0, 10
         4      EXT_STMT
         5    &gt; JMPZNZ                  9          ~1, -&gt;18
         6  &gt;   POST_INC                   ~2      !0
         7      FREE                               ~2
         8    &gt; JMP                                -&gt;3
   6     9  &gt;   EXT_STMT
        10      IS_SMALLER                 ~3      !0, 5
   7    11    &gt; JMPZ                               ~3, -&gt;15
   8    12  &gt;   EXT_STMT
        13      ECHO                               '-'
   9    14    &gt; JMP                                -&gt;17
  12    15  &gt;   EXT_STMT
        16      ECHO                               '%2B'
  14    17  &gt; &gt; JMP                                -&gt;6
  15    18  &gt;   EXT_STMT
        19      ECHO                               '%0A'
  16    20      EXT_STMT
        21    &gt; RETURN                             null

branch: #  0; line:  2- 4; sop:  0; eop:  2; out1:   3
branch: #  3; line:  4- 4; sop:  3; eop:  5; out1:  18; out2:   9
branch: #  6; line:  4- 4; sop:  6; eop:  8; out1:   3
branch: #  9; line:  6- 7; sop:  9; eop: 11; out1:  12; out2:  15
branch: # 12; line:  8- 9; sop: 12; eop: 14; out1:  17
branch: # 15; line: 12-14; sop: 15; eop: 16; out1:  17
branch: # 17; line: 14-14; sop: 17; eop: 17; out1:   6
branch: # 18; line: 15-16; sop: 18; eop: 21
path #1: 0, 3, 18,
path #2: 0, 3, 9, 12, 17, 6, 3, 18,
path #3: 0, 3, 9, 15, 17, 6, 3, 18,
End of function test.

&lt;/pre&gt;
      &lt;p&gt;This dump consists of a few different parts. First of all we can see some basic information containing the name, the number of ops (22) and the compiled variables. The second part is a dump of all the opcodes that make up this function. The last part contains information about all the branches and the possible paths.  This information is a bit hard to visualize in its textual form, so I've also added some code that dumps this information to a file format that the &lt;a href="http://graphviz.org/"&gt;GraphViz&lt;/a&gt; tool "dot" can use to create a pretty graph. For this we re-run the previous PHP invocation as &lt;code&gt;php -dvld.dump_paths=1
-dvld.verbosity=0 -dvld.save_paths=1 -dvld.active=1 test2.php&lt;/code&gt;. This creates the file &lt;code&gt;/tmp/paths.dot&lt;/code&gt; that "dot" can use. If we run &lt;code&gt;dot -Tpng
/tmp/paths.dot &gt; /tmp/paths.png&lt;/code&gt; we end up with the following picture:&lt;/p&gt;
      &lt;img src="/images/vld-paths.png" alt="vld-paths.png"/&gt;
      &lt;p&gt;If we put this graph next to the code, we can explain how this works. Every branch is named by the number of the first opcode in that branch:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #1&lt;/code&gt; is the assignment of &lt;code&gt;$i&lt;/code&gt; in line 4.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #3&lt;/code&gt; is the &lt;em&gt;loop test&lt;/em&gt; in line 4. If the condition doesn't match, we jump to &lt;code&gt;op #18&lt;/code&gt; on line 16 that echos the newline.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #9&lt;/code&gt; is the &lt;code&gt;if&lt;/code&gt; condition on line 6.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #12&lt;/code&gt; is when the &lt;code&gt;if&lt;/code&gt; condition returns true and&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #15&lt;/code&gt; is when the &lt;code&gt;if&lt;/code&gt; condition returns false.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #17&lt;/code&gt; sits behind both &lt;code&gt;op #12&lt;/code&gt; and &lt;code&gt;op #15&lt;/code&gt; and makes sure there is a jump to the counting expression in &lt;code&gt;#op 6&lt;/code&gt;.&lt;/p&gt;
        &lt;/li&gt;
        &lt;li&gt;
          &lt;p&gt;&lt;code&gt;op #6&lt;/code&gt; is the post increment operation on line 4 which will then again be followed by &lt;code&gt;op #3&lt;/code&gt; to check whether the end of the loop has been reached.&lt;/p&gt;
        &lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;This is of course a very simple example, but it also works for (multiple) classes and functions in a file. You just need to make sure to tell VLD that you don't want the code &lt;em&gt;executed&lt;/em&gt; as the output could be very large. You can use the &lt;code&gt;vld.execute=0&lt;/code&gt; php.ini setting for that.&lt;/p&gt;
      &lt;p&gt;I hope this new functionality can spread some light on how loops etc. work in PHP. In order to play with the code, you need to check-out VLD from my SVN with &lt;code&gt;svn co svn://svn.xdebug.org/svn/php/vld/trunk vld&lt;/code&gt;. You can also view the code on-line at &lt;a href="http://svn.xdebug.org/cgi-bin/viewvc.cgi/vld/trunk/?root%3Dphp"&gt;http://svn.xdebug.org/cgi-bin/viewvc.cgi/vld/trunk/?root=php&lt;/a&gt;. Look out for a new release coming soon!&lt;/p&gt;
      
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</description>
      <guid>201002191145</guid>
      <pubDate>Fri, 19 Feb 2010 11:27:00 +0000</pubDate>
    </item>
  </channel>
</rss>
