全书目录

第三十七篇:Symfony 完全指南 —— 组件化政务城区宇宙

第九章:Doctrine 是档案馆接口,但要先记住,它不是 Symfony 内核本体

1 分钟 369 字 第 706 / 962 个阅读单元

Doctrine 和 Symfony 走得很近,近到很多人会误以为:

text
Doctrine = Symfony 自带 ORM

不是。

更准确的说法是:

text
Doctrine = Symfony 官方主流数据库搭档

这件事很重要,因为它解释了 Symfony 的风格:

Symfony 不强行把所有领域都做成自己的一体内核,它更擅长把成熟部门接入同一治理体系。

安装 Doctrine 的常见方式:

bash
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle

一个典型实体会长这样:

php
<?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 管:

bash
php bin/console make:entity
php bin/console doctrine:migrations:diff
php bin/console doctrine:migrations:migrate

所以你要把关系分清:

text
Entity
= 档案对象

Repository
= 档案查询员

Migration
= 档案结构变更令

Doctrine
= 档案馆接入系统

另外还有一个特别有 Symfony 味道的细节:

php
#[Route('/permits/{id}', methods: ['GET'])]
public function show(BusinessPermit $permit): Response
{
    // ...
}

这就是 Entity Value Resolver 的便利。
简单场景下,它像窗口旁边的“自动调档员”。

但也别滥用。
如果查档逻辑复杂,回到 Repository 显式查询更清楚。