Timestampable behavior will automate the update of date fields on your Entities or Documents. It works through annotations and can update fields on creation, update or even on specific property value change.
Features:
Update 2011-04-04
Notice list:
Portability:
This article will cover the basic installation and functionality of Timestampable behavior
Content:
If you using the source from github repository, initial directory structure for the extension library should look like this:
...
/DoctrineExtensions
/lib
/Gedmo
/Exception
/Mapping
/Sluggable
/Timestampable
/Translatable
/Tree
/tests
...
...
First of all we need to setup the autoloading of extensions:
$classLoader = new \Doctrine\Common\ClassLoader('Gedmo', "/path/to/library/DoctrineExtensions/lib");
$classLoader->register();
To attach the Timestampable Listener to your event system:
$evm = new \Doctrine\Common\EventManager();
// ORM and ORM
$timestampableListener = new \Gedmo\Timestampable\TimestampableListener();
$evm->addEventSubscriber($timestampableListener);
// now this event manager should be passed to entity manager constructor
Available configuration options:
Notice: that Timestampable interface is not necessary, except in cases there you need to identify entity as being Timestampable. The metadata is loaded only once then cache is activated
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Article
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/**
* @ORM\Column(type="string", length=128)
*/
private $title;
/**
* @var datetime $created
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="date")
*/
private $created;
/**
* @var datetime $updated
*
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updated;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function getCreated()
{
return $this->created;
}
public function getUpdated()
{
return $this->updated;
}
}
namespace Document;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
/**
* @ODM\Document(collection="articles")
*/
class Article
{
/** @ODM\Id */
private $id;
/**
* @ODM\String
*/
private $title;
/**
* @var timestamp $created
*
* @ODM\Timestamp
* @Gedmo\Timestampable(on="create")
*/
private $created;
/**
* @var date $updated
*
* @ODM\Date
* @Gedmo\Timestampable
*/
private $updated;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function getCreated()
{
return $this->created;
}
public function getUpdated()
{
return $this->updated;
}
}
Now on update and creation these annotated fields will be automatically updated
Yaml mapped Article: /mapping/yaml/Entity.Article.dcm.yml
---
Entity\Article:
type: entity
table: articles
id:
id:
type: integer
generator:
strategy: AUTO
fields:
title:
type: string
length: 64
created:
type: date
gedmo:
timestampable:
on: create
updated:
type: datetime
gedmo:
timestampable:
on: update
<?xml version="1.0" encoding="UTF-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping">
<entity name="Mapping\Fixture\Xml\Timestampable" table="timestampables">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
</id>
<field name="created" type="datetime">
<gedmo:timestampable on="create"/>
</field>
<field name="updated" type="datetime">
<gedmo:timestampable on="update"/>
</field>
<field name="published" type="datetime" nullable="true">
<gedmo:timestampable on="change" field="status.title" value="Published"/>
</field>
<many-to-one field="status" target-entity="Status">
<join-column name="status_id" referenced-column-name="id"/>
</many-to-one>
</entity>
</doctrine-mapping>
Add another entity which would represent Article Type:
namespace Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Type
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/**
* @ORM\Column(type="string", length=128)
*/
private $title;
/**
* @ORM\OneToMany(targetEntity="Article", mappedBy="type")
*/
private $articles;
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
}
Now update the Article Entity to reflect published date on Type change:
namespace Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Article
{
/** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
private $id;
/**
* @ORM\Column(type="string", length=128)
*/
private $title;
/**
* @var datetime $created
*
* @Gedmo\Timestampable(on="create")
* @ORM\Column(type="date")
*/
private $created;
/**
* @var datetime $updated
*
* @ORM\Column(type="datetime")
* @Gedmo\Timestampable(on="update")
*/
private $updated;
/**
* @ORM\ManyToOne(targetEntity="Type", inversedBy="articles")
*/
private $type;
/**
* @var datetime $published
*
* @ORM\Column(type="datetime", nullable=true)
* @Gedmo\Timestampable(on="change", field="type.title", value="Published")
*/
private $published;
public function setType($type)
{
$this->type = $type;
}
public function getId()
{
return $this->id;
}
public function setTitle($title)
{
$this->title = $title;
}
public function getTitle()
{
return $this->title;
}
public function getCreated()
{
return $this->created;
}
public function getUpdated()
{
return $this->updated;
}
public function getPublished()
{
return $this->published;
}
}
Yaml mapped Article: /mapping/yaml/Entity.Article.dcm.yml
---
Entity\Article:
type: entity
table: articles
id:
id:
type: integer
generator:
strategy: AUTO
fields:
title:
type: string
length: 64
created:
type: date
gedmo:
timestampable:
on: create
updated:
type: datetime
gedmo:
timestampable:
on: update
published:
type: datetime
gedmo:
timestampable:
on: change
field: type.title
value: Published
manyToOne:
type:
targetEntity: Entity\Type
inversedBy: articles
Now few operations to get it all done:
$article = new Article;
$article->setTitle('My Article');
$em->persist($article);
$em->flush();
// article: $created, $updated were set
$type = new Type;
$type->setTitle('Published');
$article = $em->getRepository('Entity\Article')->findByTitle('My Article');
$article->setType($type);
$em->persist($article);
$em->persist($type);
$em->flush();
// article: $published, $updated were set
$article->getPublished()->format('Y-m-d'); // the date article type changed to published
Easy like that, any suggestions on improvements are very welcome