[DC-1020] In the Timestampable Listener, the 'alias' behavior option is not used when determining the database fieldname Created: 19/Jul/11 Updated: 19/Jul/11 |
|
| Status: | Open |
| Project: | Doctrine 1 |
| Component/s: | Timestampable |
| Affects Version/s: | 1.2.2, 1.2.3, 1.2.4 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major |
| Reporter: | Will Mitchell | Assignee: | Jonathan H. Wage |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Environment: |
PHP 5.3.5, MySQL 5.5.9; as well as PHP 5.3.6, MySQL 5.0.92 |
||
| Attachments: |
|
| Description |
|
I noticed this issue after setting up timestampable behavior on an aliased column in a legacy table: <?php abstract class Content_Article extends Doctrine_Record { public function setTableDefinition() { $this->setTableName('t_content'); $this->hasColumn('id', 'integer', 11, array('primary' => true, 'autoincrement' => true)); // ... $this->hasColumn('datePost as posted_at', 'timestamp'); $this->hasColumn('dateEdit as updated_at', 'timestamp'); // ... } public function setUp() { // .. $this->actAs('Timestampable', array('created' => array( 'name' => 'datePost', 'alias' => 'posted_at'), 'updated' => array( 'name' => 'dateEdit', 'alias' => 'updated_at'))); } } Before I added timestampable to this model, I was setting the timestamp fields manually, which worked fine. I had to look at the source to find the alias option in the timestampable behavior, since it does not appear to be in the 1.2 documentation. (If this issue is invalid because it's not an officially supported option, I apologize). After I added timestampable to the model, Doctrine began throwing an exception when I tried to save a new record:
It appears that the alias option is used when setting the table definition in the behavior template, but not used by the template's listener when creating, updating, etc. I'm attaching a zip with a copy of the changes I made to fix this in 1.2.4 and a git patch. |
[DC-1051] Timestampable listener does not set timestamp fields on a copy of a Doctrine_Record Created: 14/Mar/12 Updated: 06/Sep/12 |
|
| Status: | Open |
| Project: | Doctrine 1 |
| Component/s: | Timestampable |
| Affects Version/s: | 1.2.3 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major |
| Reporter: | Jeremy Johnson | Assignee: | Jonathan H. Wage |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Attachments: |
|
| Description |
|
The Timestampable Listener only sets the timestamp if the timestamp field has not been modified: if ( ! isset($modified[$createdName])) { $event->getInvoker()->$createdName = $this->getTimestamp('created', $event->getInvoker()->getTable()->getConnection()); } When saving a copy of a Doctrine_Record that doesn't already have the timestamp fields set fails to be updated, leading to integrity constraint violation ("created_at cannot be NULL"). The reason is that all unset fields in the copy are set to an instance of Doctrine_Null, which is considered to be modifed according to the condition tested for above. To fix the issue, I modified the code above to read: if ( ! isset($modified[$createdName]) || $modified[$createdName] instanceof Doctrine_Null) { $event->getInvoker()->$createdName = $this->getTimestamp('created', $event->getInvoker()->getTable()->getConnection()); } |
| Comments |
| Comment by blopblop [ 06/Sep/12 ] |
|
Your fix works great, I have also added the fix for the preupdate function and in one more place in the preinsert function. [code]
if ( ! $this->_options['updated']['disabled'] && $this->_options['updated']['onInsert']) { } } /** * Set updated Timestampable column when a record is updated * * @param Doctrine_Event $evet * @return void */ public function preUpdate(Doctrine_Event $event) { if ( ! $this->_options['updated']['disabled']) { $updatedName = $event->getInvoker() //echo "updatedName: "; var_dump(updatedName); $modified = $event->getInvoker()->getModified(); if ( ! isset($modified[$updatedName]) || $modified[$updatedName] instanceof Doctrine_Null) { $event->getInvoker()->$updatedName = $this->getTimestamp('updated', $event->getInvoker()->getTable()->getConnection()); } } Also there is another problem too. If you dont disable the widgets of the fields updated_at and created_at, sometimes they are sending the date time information in the $form, and the function preUpdate doesnt update the update_at because the date time has been sent. The best option is to disable the widgets and form validation in global scope, here: /**
if (isset($this->validatorSchema['updated_at'])) { unset($this->validatorSchema['updated_at']); }} if (isset($this->widgetSchema)) if (isset($this->widgetSchema['updated_at'])) { unset($this->widgetSchema['updated_at']); } } |
| Comment by blopblop [ 06/Sep/12 ] |
|
fixed |