Doctrine ORM para PHP: guía completa con ejemplos prácticos
1. ¿Qué es y para qué sirve?
Doctrine ORM (Object-Relational Mapper) es una potente biblioteca para PHP que implementa el patrón Data Mapper. A diferencia de Active Record (usado en Laravel Eloquent), Doctrine separa completamente la lógica de negocio (entidades) de la lógica de base de datos. Las entidades son objetos PHP simples (Plain Old PHP Objects, POPO) que no conocen la existencia de la base de datos. Todo el trabajo con la BD se realiza a través de un repositorio central: el EntityManager.
¿Para qué sirve? Doctrine resuelve el problema fundamental de desajuste entre el modelo orientado a objetos y el modelo relacional de base de datos (Object-Relational Impedance Mismatch). Trabajas con objetos y colecciones, mientras Doctrine traduce automáticamente tus acciones en consultas SQL. Esto permite escribir código más limpio, testeable y mantenible, especialmente en proyectos empresariales grandes.
Ventajas clave: control total sobre SQL (mediante DQL — Doctrine Query Language), carga diferida (Lazy Loading), sistema flexible de eventos (Lifecycle Events), soporte para herencia (Mapped Superclass, Single Table Inheritance, Joined Table Inheritance), Query Builder integrado e hidratadores (Hydration Modes). Doctrine es el estándar de facto para aplicaciones PHP complejas (Symfony, Drupal, Magento).
2. Instalación
La instalación se realiza mediante Composer (equivalente a pip para PHP). Para uso básico bastan dos paquetes:
composer require doctrine/orm
composer require doctrine/dbal
composer require symfony/cache # Recomendado para caché de metadatos
Para trabajar con anotaciones (método antiguo pero popular) se necesita un paquete adicional:
composer require doctrine/annotations
Para configuración YAML o XML:
composer require symfony/yaml # Para YAML
Después de instalar, asegúrate de incluir el cargador automático de Composer en tu proyecto:
require_once __DIR__ . '/vendor/autoload.php';
3. Inicio rápido — ejemplo mínimo funcional
Vamos a crear una entidad simple User y guardarla en una base de datos SQLite.
Paso 1: Configuración del EntityManager (bootstrap.php)
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMSetup;
use Doctrine\DBAL\DriverManager;
require_once __DIR__ . '/vendor/autoload.php';
// Configurar rutas de entidades y modo de desarrollo
$paths = [__DIR__ . '/src/Entity'];
$isDevMode = true;
// Crear configuración ORM
$config = ORMSetup::createAttributeMetadataConfiguration($paths, $isDevMode);
// Configurar conexión a BD (SQLite)
$connectionParams = [
'driver' => 'pdo_sqlite',
'path' => __DIR__ . '/data/database.sqlite',
];
$connection = DriverManager::getConnection($connectionParams, $config);
// Crear EntityManager
$entityManager = new EntityManager($connection, $config);
Paso 2: Crear la entidad (src/Entity/User.php)
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'users')]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private int|null $id = null;
#[ORM\Column(type: 'string', length: 100)]
private string $name;
#[ORM\Column(type: 'string', length: 255, unique: true)]
private string $email;
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): self También en la biblioteca
Trabajo con CSV en TypeScript: bibliotecas y ejemplos de código
Clap para Rust: guía completa con ejemplos
Validación de datos en Java: revisión de bibliotecas y enfoques
Validación de datos en Swift: biblioteca Validator
Planificador de tareas en TypeScript: guía detallada de la biblioteca node-schedule