Doctrine 和 Symfony 走得很近,近到很多人会误以为:
Doctrine = Symfony 自带 ORM不是。
更准确的说法是:
Doctrine = Symfony 官方主流数据库搭档这件事很重要,因为它解释了 Symfony 的风格:
Symfony 不强行把所有领域都做成自己的一体内核,它更擅长把成熟部门接入同一治理体系。
安装 Doctrine 的常见方式:
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle一个典型实体会长这样:
<?php
namespace App\Entity;
use App\Repository\BusinessPermitRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity(repositoryClass: BusinessPermitRepository::class)]
class BusinessPermit
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 120)]
#[Assert\NotBlank]
#[Assert\Length(max: 120)]
private string $applicantName = '';
#[ORM\Column(length: 160)]
#[Assert\NotBlank]
#[Assert\Length(max: 160)]
private string $businessName = '';
#[ORM\Column(length: 20)]
private string $status = 'draft';
#[ORM\Column(type: 'datetime_immutable')]
private \DateTimeImmutable $createdAt;
#[ORM\Column(type: 'datetime_immutable', nullable: true)]
private ?\DateTimeImmutable $submittedAt = null;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
public function markSubmitted(): void
{
$this->status = 'submitted';
$this->submittedAt = new \DateTimeImmutable();
}
public function getId(): ?int
{
return $this->id;
}
public function getBusinessName(): string
{
return $this->businessName;
}
public function getStatus(): string
{
return $this->status;
}
}这段代码把两套规则放在了一起:
- Doctrine 的映射规则:这个对象如何进档案馆
- Validator 的校验规则:这份申请表什么才算合格
而结构变更靠 migration 管:
php bin/console make:entity
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate所以你要把关系分清:
Entity
= 档案对象
Repository
= 档案查询员
Migration
= 档案结构变更令
Doctrine
= 档案馆接入系统另外还有一个特别有 Symfony 味道的细节:
#[Route('/permits/{id}', methods: ['GET'])]
public function show(BusinessPermit $permit): Response
{
// ...
}这就是 Entity Value Resolver 的便利。
简单场景下,它像窗口旁边的“自动调档员”。
但也别滥用。
如果查档逻辑复杂,回到 Repository 显式查询更清楚。