Entities and migrations
Symfony works with the database through Doctrine. Each table has an entity — a plain PHP class — and each row is its object. Unlike Laravel models, an entity knows nothing about the database: a separate object does the saving.
Connecting
The database address is set in the .env file:
DATABASE_URL="mysql://root:secret@127.0.0.1:3306/blog?serverVersion=8.0.32&charset=utf8mb4"A command creates the database itself:
php bin/console doctrine:database:createCreating an entity
php bin/console make:entity PostThe command asks about each field: name, type, length, whether it may be empty. Two files appear as a result — the entity and its repository.
What an entity looks like
// src/Entity/Post.php
namespace App\Entity;
use App\Repository\PostRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: PostRepository::class)]
class Post
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $body = null;
#[ORM\Column]
private bool $published = false;
public function getId(): ?int
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): static
{
$this->title = $title;
return $this;
}
// the remaining get and set methods
}The #[ORM\Column] attributes describe the columns. Properties are private and accessed through methods.
Column parameters
| Form | Meaning |
|---|---|
#[ORM\Column(length: 100)] | A string of up to 100 characters |
#[ORM\Column(nullable: true)] | May be empty |
#[ORM\Column(unique: true)] | Values do not repeat |
#[ORM\Column(type: Types::TEXT)] | Long text |
#[ORM\Column(options: ['default' => 0])] | A default value |
Doctrine usually works out the column type from the property type: int, string, bool, float, \DateTimeImmutable.
The migration
An entity is only a description. A migration creates the table:
php bin/console make:migration
php bin/console doctrine:migrations:migrateThe first command compares the entities with the database and writes the difference to a file in the migrations folder. The second one runs it.
Changing the structure
To add a field, run make:entity Post again and answer the questions — or add the property by hand. Then create and run a new migration. The database structure changes step by step this way, and every step is kept in the project repository.
Common mistake
The doctrine:schema:update --force command changes the database at once, without a migration file. That is handy on your own machine, but on a server such changes cannot be repeated or undone. Change a production database only with migrations, and read the generated file before running it: Doctrine may propose dropping a column together with its data.