I'm using Symfony2.2 with StofDoctrineExtensionsBundle (and so Gedmo DoctrineExtensions). I've a simple entity
/**
* @ORM\Entity
* @Gedmo\Loggable
* @ORM\Table(name="person")
*/
class Person {
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
[...]
/**
* @ORM\Column(type="datetime", nullable=true)
* @Assert\NotBlank()
* @Assert\Date()
* @Gedmo\Versioned
*/
protected $birthdate;
}
When changing an attribute for an existing object, a log entry is done in table ext_log_entries
. An entry in this log table contains only changed columns. I can read the log by:
$em = $this->getManager();
$repo = $em->getRepository('Gedmo\Loggable\Entity\LogEntry');
$person_repo = $em->getRepository('Acme\MainBundle\Entity\Person');
$person = $person_repo->find(1);
$log = $repo->findBy(array('objectId' => $person->getId()));
foreach ($log as $log_entry) { var_dump($log_entry->getData()); }
But what I don't understand is, why the field birthdate
is always contained in a log entry, even it's not changed. Here some examples of three log entries:
array(9) {
["salutation"]=>
string(4) "Herr"
["firstname"]=>
string(3) "Max"
["lastname"]=>
string(6) "Muster"
["street"]=>
string(14) "Musterstraße 1"
["zipcode"]=>
string(5) "00000"
["city"]=>
string(12) "Musterhausen"
["birthdate"]=>
object(DateTime)#655 (3) {
["date"]=>
string(19) "1893-01-01 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
["email"]=>
string(17) "[email protected]"
["phone"]=>
NULL
}
array(2) {
["birthdate"]=>
object(DateTime)#659 (3) {
["date"]=>
string(19) "1893-01-01 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
["phone"]=>
string(9) "123456789"
}
array(2) {
["birthdate"]=>
object(DateTime)#662 (3) {
["date"]=>
string(19) "1893-01-01 00:00:00"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
["phone"]=>
NULL
}
I want to log only really changed data. Is there any option I've not seen yet? It seems to be related to the fact, that birthdate
is a DateTime
object, doesn't it?
EDIT
It is not related to the DateTime
object. This occurs even in other entities. I've another entity containing a simple value:
/**
* @ORM\Entity
* @Gedmo\Loggable
* @ORM\Entity(repositoryClass="Acme\MainBundle\Repository\ApplicationRepository")
* @ORM\Table(name="application")
*/
class Application {
[...]
/**
* @ORM\Column(type="integer")
* @Assert\NotBlank(groups={"FormStepOne", "UserEditApplication"})
* @Gedmo\Versioned
*/
protected $insurance_number;
}
When opening the edit form in browser an saving without modification, the log table contains:
update 2013-04-26 11:32:42 Acme\MainBundle\Entity\Application a:1:{s:16:"insurance_number";s:7:"1234567";}
update 2013-04-26 11:33:17 Acme\MainBundle\Entity\Application a:1:{s:16:"insurance_number";s:7:"1234567";}
Why?
This might be a similar issue to the one I encountered when using another of these extensions (timestampable), namely: that the default change tracking policy used in doctrine (it tries to auto detect changes) sometimes marks entities as dirty, when they are not (for me this was happening when my entity contained a datetime object, which is understandable given that this is an object which needs to be constructed when pulling it from the database). This isn't a bug or anything - it's expected behaviour and there are a few ways around it.
Might be worth trying to implement an alternative change tracking policy on the entities you want to log and seeing if that fixes things - I would guess that this behaviour (logging) doesn't kick in unless the entity state is dirty, which you can avoid by implementing change tracking yourself manually:
Don't forget to update your entity:
YourBundle\Entity\YourThing:
type: entity
table: some_table
changeTrackingPolicy: NOTIFY
See this thread:
https://github.com/Atlantic18/DoctrineExtensions/issues/333#issuecomment-16738878