WarningIt’s almost half a month ago since PHP 5.2.4 was released and since I really like to update software ;-) I immediately upgraded from 5.2.3 – but the result was rather shocking – all my Symfony projects stopped working because of a Exception thrown by Propel: “Error populating Pages object [wrapped: Unable to convert value at column 13 to timestamp: 0000-00-00 00:00:00]“.

I watched the Symfony forums/mailing lists and the Propel mailing lists, but nothing similar was posted so that i tracked it down on my own and found the issue in Creole (DBAL used by Propel, which is used by Symfony).

The issue lies in the getTimestamp() function (Line 126 in creole/drivers/mysql/MySQLResultSet.php), which basically just converts a date from your database to a unix timestamp.Let’s say that your database field has the default value “0000-00-00 00:00:00” set on a datetime field and the getTimestamp() function tries to parse this default value with strtotime, which worked fine in PHP 5.2.3 and below since this function would return “943905600” (which equals to 1999-11-30, but don’t ask me why…) but was fixed in PHP 5.2.4. The function now returns boolean FALSE which is causing the function to fail and throw an Exception.

It’s okay that strtotime doesn’t accept “0000-00-00 00:00:00” as a date and returns false instead, but since this value is often used as a default for a datetime field in Propel and will break your application(s).Unfortunately Creole is not actively maintained anymore, so don’t expect a fix for this issue, but you can of course fix it yourself like this:

if ($this->fields[$column] == '0000-00-00 00:00:00') {    // If the value is  '0000-00-00 00:00:00', set it back to the value strtotime() returned before PHP 5.2.4    $ts = '943916400';}else {    $ts = strtotime($this->fields[$column]);}

You can try the fix and work with Symfony and PHP 5.2.4, but I will go back to PHP 5.2.3 since i can’t be 100% sure that there is another error somewhere.Please state your opinion in the comments, thanks!

Update: Seth Wilson found another instance of this bug in \pear\symfony\vendor\creole\common\ResultSetCommon.php at line 356:

if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE throw new SQLException("Unable to convert value at column " . $column . " to timestamp: " . $this->fields[$idx]);}

To fix it, just change it to :

if ($ts === -1 || $ts === false) { // in PHP 5.1 return value changes to FALSE  return '943916400';  #throw new SQLException("Unable to convert value at column " . $column . " to timestamp: " . $this->fields[$idx]);}

Thanks Seth!

Update 2: Symfony 1.0.9 fixes this problem, be sure to upgrade!


		
Advertisements

Huh? a bug!The sfFillInFilter is really useful for form repopulation and often saves a great deal of time, but if you’ve worked with it you may also have noticed that, after a form repopulation, all of your xhtml-compliant code is transformed to regular html and thus breaks validation.
I noticed this on a project of mine where some parts of the site would render slightly different after a form repopulation, which caused me to investigate this topic a little bit.

Initially reported for symfony 0.6
, it resulted in the addition of the „content_type“ parameter for the 1.0 release. If the parameter passes „xml“, DomDocument in sfFillInFormFilter will load and save XML rather than regular HTML. This seemed to work at first but with some time passed, another serious issue showed up with „xml“ as „content_type“ set. The form repopulation won’t work because the specified form cannot be found by the sfFillInFormFilter. This issue existed for quite some time.

In April 2007, ReeD started a forum thread about this issue and quickly found out that the DOMXPath cannot select elements of an XML document with default namespace defined.
With some help from vanchuck a patch was created and attached to trac, but as of today wasn’t included in trunk.

Testing

To show you how symfony behaves with and without the patch applied, i performed a small test with a fresh symfony 1.0.6 installation, a simple form with a few input fields and a small YAML validation file which just enables the sfFillInFormFilter and passes the form name to it:

fillin:
  enabled: true
  param:
    name: register

With the form put on a valid xhtml page, repopulated and redisplayed again, all of the self-closing tags like <input … /> are now converted to it’s non-selfclosing counterpart.
By adding the „content_type“ parameter and setting it to „xml“:

fillin:
  enabled: true
  param:
    name: register
    content_type: xml

the output is valid xhtml, but symfony now throws an „No form found in this page“ error and the form fields are not repopulated.

With the patch (which is mentioned above) applied to sfFillInForm.class.php and the same validation files as before, it will still needs the „content_type“ parameter set to „xml“. Without the paramter it still won’t find the form and repopulate it. But if the parameter is passed, sfFillInFormFilter will find your form and finally output valid xhtml!

Summary

To summarize it a little bit, here are three possible solutions that i came up with to get valid xhtml in symfony 1.0:

  1. Not using xhtml for your page.
  2. Not using sfFillInFormFilter.
  3. Applying the patch and always setting the „content_type“ parameter to „xml“ in your validation files.

Since most of the build-in symfony helpers are using xhtml, it can be quite hard to migrate your code to regular html. You’ll either have not to use or rewrite them, which can take quite a time.
Not using the sfFillInFormFilter seems nice at first, but can be very time-consuming if you have forms with many fields to repopulate.
By using the patch you’ll always have to remember to set the „content_type“ parameter to „xml“ in your validation files.

Or maybe just wait for symfony 1.1 with its new and shiny form layer? You decide it! but for now i just hope that i could clear up this topic a little bit.
Please take some time and state your opinion in the comments, thanks!