Doctrine ORM 用于 PHP:完整指南及示例
\n\n1. 这是什么以及为什么需要它?
\nDoctrine ORM(对象关系映射器)是一个强大的 PHP 库,实现了 Data Mapper 模式。与 Active Record(在 Laravel Eloquent 中使用)不同,Doctrine 将业务逻辑(实体)与数据库操作逻辑完全分离。实体是普通的 PHP 对象(Plain Old PHP Objects, POPO),它们不知道数据库的存在。所有与数据库的交互都通过中央仓库 EntityManager 进行。
\n\n为什么需要它?Doctrine 解决了面向对象数据模型与关系数据库模型之间的根本性不匹配问题(对象关系阻抗不匹配)。您处理对象和集合,而 Doctrine 会自动将您的操作转换为 SQL 查询。这使得您可以编写更干净、更可测试且更易于维护的代码,尤其是在大型企业项目中。
\n\n关键优势:对 SQL 的完全控制(通过 DQL——Doctrine 查询语言)、延迟加载(Lazy Loading)、灵活的事件系统(Lifecycle Events)、支持继承(Mapped Superclass、Single Table Inheritance、Joined Table Inheritance)、内置的 Query Builder 和 Hydrator(Hydration Modes)。Doctrine 是复杂 PHP 应用程序(Symfony、Drupal、Magento)的事实标准。
\n\n2. 安装
\n通过 Composer(PHP 的 pip 对应工具)进行安装。基本使用只需两个包:
\ncomposer require doctrine/orm\ncomposer require doctrine/dbal\ncomposer require symfony/cache # 建议用于元数据缓存\n\n要使用注解(已过时但流行的方法),需要额外的包:
\ncomposer require doctrine/annotations\n\n要使用 YAML 或 XML 配置:
\ncomposer require symfony/yaml # 用于 YAML\n\n安装后,请确保在您的项目中包含了 Composer 的自动加载器:
\nrequire_once __DIR__ . '/vendor/autoload.php';\n\n3. 快速入门——最小工作示例
\n让我们创建一个简单的 User 实体并将其保存到 SQLite 数据库中。
步骤 1:配置 EntityManager (bootstrap.php)
\nuse Doctrine\\ORM\\EntityManager;\nuse Doctrine\\ORM\\ORMSetup;\nuse Doctrine\\DBAL\\DriverManager;\n\nrequire_once __DIR__ . '/vendor/autoload.php';\n\n// 设置实体路径和开发模式\n$paths = [__DIR__ . '/src/Entity'];\n$isDevMode = true;\n\n// 创建 ORM 配置\n$config = ORMSetup::createAttributeMetadataConfiguration($paths, $isDevMode);\n\n// 配置数据库连接 (SQLite)\n$connectionParams = [\n 'driver' => 'pdo_sqlite',\n 'path' => __DIR__ . '/data/database.sqlite',\n];\n\n$connection = DriverManager::getConnection($connectionParams, $config);\n\n// 创建 EntityManager\n$entityManager = new EntityManager($connection, $config);\n\n步骤 2:创建实体 (src/Entity/User.php)
\nnamespace App\\Entity;\n\nuse Doctrine\\ORM\\Mapping as ORM;\n\n#[ORM\\Entity]\n#[ORM\\Table(name: 'users')]\nclass User\n{\n #[ORM\\Id]\n #[ORM\\GeneratedValue]\n #[ORM\\Column(type: 'integer')]\n private int|null $id = null;\n\n #[ORM\\Column(type: 'string', length: 100)]\n private string $name;\n\n #[ORM\\Column(type: 'string', length: 255, unique: true)]\n private string $email;\n\n public function getId(): ?int\n {\n return $this->id;\n }\n\n public function getName(): string\n {\n return $this->name;\n }\n\n public function setName(string $name): self\n {\n $this->name = $name;\n return $this;\n }\n\n public function getEmail