Doctrine ORM 在 Symfony 5.4+ 中默认集成于 symfony/orm-pack,无需手动安装;实体类须置于 src/Entity 并使用 #[ORM\Entity] 注解,配置通过 config/packages/doctrine.yaml 管理,数据库需先执行 doctrine:database:create 再建表。

Doctrine ORM 在 Symfony 5 中默认已集成,无需手动 require
Symfony 5.4+(包括所有 5.x LTS 版本)默认通过 symfony/orm-pack 预装 Doctrine ORM 及相关组件。运行 composer create-project symfony/skeleton myapp 后,doctrine/orm、doctrine/doctrine-bundle 和 doctrine/doctrine-migrations-bundle 都已自动安装并启用。直接检查 config/bundles.php,你会看到 Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true] 已存在——这意味着你跳过了“安装”环节,只需确认配置即可。
关键配置文件是 config/packages/doctrine.yaml,不是 doctrine.php 或 cli-config.php
Symfony 使用 YAML 配置驱动 Doctrine,而非手动构建 EntityManager 实例。常见错误是照搬旧项目或非 Symfony 环境的 PHP 配置(如 cli-config.php),这会导致 Bundle 无法接管生命周期,引发 ServiceNotFoundException 或 EntityManager is not configured 错误。
-
doctrine.yaml中的dbal段必须包含url或显式拆解host/port/user/password/dbname,且url优先级最高(会覆盖其他字段) -
orm段下auto_generate_proxy_classes在 dev 环境应为true,prod 必须设为false并配合php bin/console doctrine:generate:proxies手动生成 - 若使用 SQLite,
driver: pdo_sqlite且path必须是绝对路径(如%kernel.project_dir%/var/data.db),相对路径会静默失败
实体类必须放在 config/doctrine/ 能扫描到的目录,默认是 src/Entity
Symfony 的 DoctrineBundle 默认只扫描 src/Entity 下带 #[ORM\Entity] 或 @ORM\Entity 注解的类。如果你把实体放在 src/Model 或 app/Entity,即使文件存在,php bin/console doctrine:schema:update --dump-sql 也会显示 “No metadata found”,且 make:entity 命令生成的类会被放错位置。
- 确认
doctrine.yaml中mappings配置未被意外覆盖;默认配置中Appmapping 的dir是%kernel.project_dir%/src/Entity - PHP 8.1+ 推荐用 Attributes(如
#[ORM\Entity]),但注解(@ORM\Entity)仍完全兼容;混用时注意命名空间导入(use Doctrine\ORM\Mapping as ORM;) - 实体类名必须与文件名一致(
User.php→class User),否则 Doctrine 无法反射加载
第一次运行前务必执行 php bin/console doctrine:database:create
很多人卡在“表不存在”或“Connection refused”,其实只是数据库本身没建好。doctrine:schema:create 不会自动创建数据库(DB),只建表(tables)。而 doctrine:database:create 才真正调用 PDO 创建 DB 实例。
- MySQL 场景下,确保
database_url中的数据库名(如mysql://root:pass@127.0.0.1:3306/myapp)对应 DB 尚未存在,命令才会成功创建 - PostgreSQL 用户需提前创建好角色(role),
database_url中的user必须有CREATEDB权限 - 执行后立即跟
doctrine:schema:create --force或doctrine:migrations:migrate(如果已初始化迁移)
$entityManager = $this->getDoctrine()->getManager() 或类型化注入 EntityManagerInterface 就能直接用了。最容易被忽略的是:**YAML 缩进必须用空格,不能用 Tab;数据库 URL 中密码含特殊字符(如 @、/)必须 URL-encode;以及 prod 环境下 proxy 类路径写错会导致 fatal error —— 这些都不会报明确异常,只会静默失败或抛出难以溯源的 ReflectionException。**


















