A pesky and difficult to debug doctrine problem I’ve been encountering is the following occurring after a flush() call:
PHP Fatal error: Call to a member function format() on a non-object in /var/www/myapp/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/DateTimeType.php on line 53
Obviously this gives no info on the actual cause of the error, which it turns out is because of a mismatch between doctrine expecting a DateTime object and instead encountering a string object, which does not have a format() function to call.
The solution is to remove the default string value that doctrine’s orm tools sometimes wrongly attaches to objects and instead use the correct DateTime() object, e.g.:
protected $timestamp = '0000-00-00 00:00:00';
The first problem if you have a lot of model files is actually finding where the problem is. Whilst there are a host of debug tools which can help, a quick and easy hack is to simply add a stacktrace to the offending doctrine vendor file.
First go to your project’s main folder and vim the relevant file, if you are not a vim file, the substitute it for another one of the many text editors out there:
Then go to line 53 (or whatever line number appears in the error message) by typing
:53 (i.e. a semi-colon followed by the line number) where you should see a line reading:
return ($value !== null)
? $value->format($platform->getDateTimeFormatString()) : null;
Go up one line above this and press the
a key to enter insert mode and enter:
A good tip is to save the file using
:w, but don’t actually close the file. Running your application again you will then print out the usual – hideously ugly – stacktrace. This can be filtered down but even just loooking at the raw ouput should reveal the reflection classes inspecting the model file a couple of steps down which has the incorrectly set line exampled above. This is where you then remove the changes from the above file, by pressing
u to undo the changes. Followed by
:q to quit the file.
This string needs to be changed to a DateTime() object and you will need to set a default value in the constructor, e.g.:
public function __construct()
$this->timestamp = new \DateTime();
Leaving out the parameter will be set it to the current system time. This will lead to doctrine correctly interpreting and saving timestamps to the database upon flush.
A more complete strategy to automating timestamp & date generation for data using Doctrine is present in my article:
Automating timestamps with Doctrine ORM