Doctrine ORM需手动配置连接、元数据路径、代理目录等,否则报ClassNotFoundException或返回null;doctrine/orm为纯PHP库,非Symfony项目应选它,Symfony项目用doctrine/doctrine-bundle,Laravel用laravel-doctrine/orm。

直接用 composer require 就能装 Doctrine ORM,但光执行命令远远不够——它默认不带配置、不建连接、不生成代理类,项目一跑就报 ClassNotFoundException 或 ConnectionException。
doctrine/orm 包和 doctrine/doctrine-bundle 有什么区别?
这是最常混淆的点:前者是纯 PHP ORM 库(无 Symfony 依赖),后者是 Symfony 的集成绑定包。如果你用的是原生 PHP、Laravel、Slim 或其他非 Symfony 框架,别装 doctrine/doctrine-bundle,它会强行拉入一堆 Symfony 组件,还报 Class 'Symfony\Component\DependencyInjection\ContainerBuilder' not found。
- 纯 PHP / 自研框架 → 只装
doctrine/orm+doctrine/dbal+doctrine/common(后两者通常由doctrine/orm自动依赖) - Symfony 项目 → 装
doctrine/doctrine-bundle,它会帮你配好 YAML、自动注册服务、处理生命周期事件 - Laravel 项目 → 用
laravel-doctrine/orm,原生doctrine/orm不兼容 Laravel 的容器和服务发现机制
require 后必须手动初始化 EntityManager
Composer 安装完 doctrine/orm,不会自动生成 EntityManager 实例,也不会读取任何配置文件。你得自己写引导逻辑,否则所有 $em->persist() 都会报错。
- 先创建配置数组,重点设
driver(推荐pdo_mysql)、host、dbname、user、password - 用
Setup::createAnnotationMetadataConfiguration()构建$config,注意第二个参数$isDevMode设为true才会启用代理类自动生成 - 调用
EntityManager::create(),传入连接配置和$config,返回可用的$em - 代理类目录必须可写(如
./proxies),否则开发模式下第一次 flush 就卡住
示例片段:
$paths = [__DIR__.'/src/Entity']; $isDevMode = true; $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode, './proxies'); $connection = ['driver' => 'pdo_mysql', 'host' => 'localhost', 'dbname' => 'test', 'user' => 'root', 'password' => '']; $em = EntityManager::create($connection, $config);
实体类注解不生效?检查 autoloader 和扫描路径
Doctrine 默认用注解驱动(@ORM\Entity 等),但如果你的实体类没被 createAnnotationMetadataConfiguration() 的 $paths 参数覆盖,或者 Composer 的 autoloader 没加载到该命名空间,就会静默跳过——$em->find() 返回 null,也不报错。
-
$paths必须是绝对路径,推荐用__DIR__或dirname(__DIR__)拼接,别用相对路径 - 实体类
namespace必须和autoload.psr-4中定义的一致,比如"App\\Entity\\": "src/Entity/",那类就得声明namespace App\Entity; - 运行
composer dump-autoload确保新类已注册,尤其在加了新 Entity 后 - 如果坚持用 XML 或 YAML 映射,就得换用
createXMLMetadataConfiguration()并指定.dcm.xml文件路径
Doctrine ORM 的核心陷阱不在安装命令,而在配置链的每个环节都要求显式声明:连接要手写、元数据要指定路径、代理类目录要可写、autoloader 要对齐命名空间——漏掉任意一环,它都不会提醒你,只会让查询返回空或抛出模糊异常。










