Buy

Creating an Entity Class

Doctrine is an ORM, or object relational mapper. A fancy term for a pretty cool idea. It means that each table in the database will have a corresponding class in our code. So if we want to create an article table, it means that we need to create an Article class. You can totally make this class by hand - it's just a normal PHP class.

Generating with make:entity

But there's a really nice generation tool from MakerBundle. We installed MakerBundle in the last tutorial, and before I started coding, I updated it to the latest version to get this new command. At your terminal, run:

php bin/console make:entity

Stop! That word "entity": that's important. This is the word that Doctrine gives to the classes that are saved to the database. As you'll see in a second, these are just normal PHP classes. So, when you hear "entity", think:

That's a normal PHP class that I can save to the database.

Let's call our class Article, and then, cool! We can start giving it fields right here. We need a title field. For field "type", hmm, hit "?" to see what all the different types are.

Notice, these are not MySQL types, like varchar. Doctrine has its own types that map to MySQL types. For example, let's use "string" and let the length be 255. Ultimately, that'll create a varchar column. Oh, and because we probably want this column to be required in the database, answer "no" for nullable.

Next, create a field called slug, use the string type again, and let's make it's length be 100, and no for nullable.

Next, content, set this to text and "yes" to nullable: maybe we allow articles to be drafted without content at first. And finally, a publishedAt field with a type set to datetime and yes to nullable. If this field is null, we'll know that the article has not been published.

When you're done, hit enter to finish. And don't worry if you make a mistake. You can always update things later, or delete the new entity class and start over.

Investigating the Entity Class

So... what did that just do? Only one thing: in src/Entity, this command generated a new Article class:

93 lines src/Entity/Article.php
... lines 1 - 2
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
*/
class Article
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="string", length=100)
*/
private $slug;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $content;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $publishedAt;
public function getId()
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(?string $content): self
{
$this->content = $content;
return $this;
}
public function getPublishedAt(): ?\DateTimeInterface
{
return $this->publishedAt;
}
public function setPublishedAt(?\DateTimeInterface $publishedAt): self
{
$this->publishedAt = $publishedAt;
return $this;
}
}

Well... to be fully honest, there is also a new ArticleRepository class, but I want you to ignore that for now. It's not important yet.

Anyways, this Article class is your entity. And, check it out! It's a normal, boring PHP class with a property for each column: id, title, slug, content, and publishedAt:

93 lines src/Entity/Article.php
... lines 1 - 9
class Article
{
... lines 12 - 16
private $id;
... lines 18 - 21
private $title;
... lines 23 - 26
private $slug;
... lines 28 - 31
private $content;
... lines 33 - 36
private $publishedAt;
... lines 38 - 91
}

What makes this class special are the annotations! The @ORM\Entity above the class tells Doctrine that this is an entity that should be mapped to the database:

93 lines src/Entity/Article.php
... lines 1 - 4
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
*/
class Article
{
... lines 12 - 91
}

Then, above each property, we have some annotations that help doctrine know how to store that exact column:

93 lines src/Entity/Article.php
... lines 1 - 4
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleRepository")
*/
class Article
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="string", length=100)
*/
private $slug;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $content;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $publishedAt;
... lines 38 - 91
}

Actually, find your browser and Google for "doctrine annotations reference" to find a cool page. This shows you every annotation in Doctrine and every option for each one.

Back at the code, the properties are private. So, at the bottom of the class, the command generated getter and setter for methods for each one:

93 lines src/Entity/Article.php
... lines 1 - 9
class Article
{
... lines 12 - 38
public function getId()
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getSlug(): ?string
{
return $this->slug;
}
public function setSlug(string $slug): self
{
$this->slug = $slug;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(?string $content): self
{
$this->content = $content;
return $this;
}
public function getPublishedAt(): ?\DateTimeInterface
{
return $this->publishedAt;
}
public function setPublishedAt(?\DateTimeInterface $publishedAt): self
{
$this->publishedAt = $publishedAt;
return $this;
}
}

There's one really important thing to realize: this class is 100% your class. Feel free to add, remove or rename any properties or methods you want.

And... yea! With one command, our entity is ready! But, the database is still empty! We need to tell Doctrine to create the corresponding article table in the database. We do this with migrations.

Leave a comment!

  • 2018-05-07 Victor Bocharsky

    Hey Yeison,

    Yeah, you're right. But this tutorial is the third one based on this "Stellar" project and we've already installed this MakerBundle in previous tutorial, see: https://knpuniversity.com/s... . So if you're with us from the beginning of the Symfony 4 track - you should have this bundle installed already :)

    But thanks for this tip for others, it may be useful.

    Cheers!

  • 2018-05-06 Yeison J. Espinoza

    Hi, i think there is a missing part:
    when you use ".bin/console make:entity", you need to install that "make" to be able to run "make" :D