Symfony perfect entity, dates and data

Anton Lytvynov
4 min readJun 21, 2018

How to set a date and data in Entity ? DateTime, createAt, updateAt and entities data

A lot of companies have some trobles with entities. It looks like this is the easiest part of your project. But here is two questions I would like to discuss :

  • dates
  • entity data

Dates with \DateTime

What is the best way to work with dates in php ? In my opinion the answer DateTime class. This is the officiel php documentation http://php.net/manual/ru/class.datetime.php

So in your class you can add two properties createdAt, updatedAt

/**
*
@var \DateTime
*/
protected $createdAt;

/**
*
@var \DateTime
*/
protected $updatedAt;
/**
*
@return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}

/**
*
@param \DateTime $createdAt
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
}

/**
*
@return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}

/**
*
@param \DateTime $updatedAt
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
}

Doctrine and Lifecycle Callbacks

If you use Doctrine in your Symfony project you can make your life much easier. Doctrine supports entity lificycle http://symfony.com/doc/current/doctrine/lifecycle_callbacks.html

So I would like to advise you to use traits TimestampableEntity and create one trait for all entities http://php.net/manual/en/language.oop5.traits.php

<?php

namespace
AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

trait TimestampableEntity
{
/**
*
@var \DateTime
*
*
@ORM\Column(type="datetime", nullable=true)
*/
protected $createdAt;

/**
*
@var \DateTime
*
*
@ORM\Column(type="datetime", nullable=true)
*/
protected $updatedAt;


/**
*
@return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}

/**
*
@param \DateTime $createdAt
*/
public function setCreatedAt($createdAt)
{
$this->createdAt = $createdAt;
}

/**
*
@return \DateTime
*/
public function getUpdatedAt()
{
return $this->updatedAt;
}

/**
*
@param \DateTime $updatedAt
*/
public function setUpdatedAt($updatedAt)
{
$this->updatedAt = $updatedAt;
}

/**
*
@ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps()
{
$this->setUpdatedAt(new \DateTime('now'));

if ($this->getCreatedAt() == null) {
$this->setCreatedAt(new \DateTime('now'));
}
}
}

And now all you need is to add a @ORM\HasLifecycleCallbacks annotation and use TimestampableEntity trait in your Entity.

<?php

namespace
AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
*
@ORM\Entity(repositoryClass="AppBundle\Repository\AppRepository")
*
@ORM\Table(name="PRODUCT")
*
@ORM\HasLifecycleCallbacks
*/
class Product
{
use TimestampableEntity;

/**
*
@var int
*
*
@ORM\Column(name="id", type="integer", nullable=false)
*
@ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
*
@var float
*
*
@ORM\Column(type="float", nullable=true)
*/
protected $price;

/**
*
@var int
*
*
@ORM\Column(type="integer", nullable=true)
*/
protected $amount;

/**
*
@return int
*/
public function getId(): int
{
return $this->id;
}

/**
*
@return float
*/
public function getPrice(): float
{
return $this->price;
}

/**
*
@param float $price
*/
public function setPrice(float $price)
{
$this->price = $price;
}

/**
*
@return int
*/
public function getAmount(): int
{
return $this->amount;
}

/**
*
@param int $amount
*/
public function setAmount(int $amount)
{
$this->amount = $amount;
}
}

In this case, all your entities have the same format of dates and you need to create or update your entities dates.

Entity data

To load all data at the same time from the array we use the same solution (trait). For example, we can name it DataLoader.

<?php

namespace
AppBundle\Traits;

use Doctrine\Common\Inflector\Inflector;

trait DataLoader
{
/**
*
@param array $data
*
*
@return $this
*/
public function loadData(array $data)
{
foreach ($data as $key => $value) {
$method = Inflector::camelize('set_' . $key);
if (method_exists($this, $method)) {
$this->$method($value);
}
}

return $this;
}
}

In this case, in our Product we need to add the second trait

...
class
Product
{
use TimestampableEntity;
use DataLoader;
...

To use it :

$product = new Product();
$product->loadData(
[
'price' => 12.23,
'amount' => 10,
]
);

Entity properties to Array

If you need to convert our entity to the array, in this case, I use the other trait

<?php

namespace
AppBundle\Traits;

trait RawLoader
{
/**
*
@return array
*/
public function toArray()
{
return get_object_vars($this);
}
}

Use trait in class :

...
class
Product
{
use TimestampableEntity;
use DataLoader;
use RawLoader;
...

And then you can get all product’s properties as an array

$product->toArray();

GitHub

I added two simple repositories with these traits.

Other articles

By the way, probably Logging with Monolog article can be interesting for you.

Thank you for your attention!

Thank you very much for your attention! If you have any question or advice please feel free to contact me. I will be glad to help you.

Need professional help in web or mobile development?
Recommendation for planning or estimation of your project?
Feel free to contact me here.

P.S. I really appreciate your like or share.

--

--

Anton Lytvynov

CEO & Founder of Lytvynov Production, Senior web developer, architect, cryptocurrencies trader, https://lytvynov-production.com