🗄️
Doctrine ORM en modulos PrestaShop 8/9
Actualizado: 2024-12-01
Doctrine ORM es el sistema de persistencia moderno para modulos de PrestaShop 8/9. A diferencia de ObjectModel, Doctrine usa mapeo objeto-relacional con anotaciones PHP y el EntityManager de Symfony para gestionar el ciclo de vida de los objetos.
| Aspecto | ObjectModel | Doctrine ORM |
|---|---|---|
| Compatibilidad | PS 1.5+ | PS 1.7.6+ |
| Paradigma | ActiveRecord (heredar de ObjectModel) | DataMapper (POPO + anotaciones) |
| Multilenguaje | $definition con 'lang'=>true | Entidad separada MyEntityLang |
| Multishop | $definition con 'shop'=>true | Trait/asociacion por id_shop |
| Consultas | ObjectModel::getByIdLang() | QueryBuilder de Doctrine DBAL |
| Instalacion BD | Sql manual en install() | SchemaTool::createSchema() |
| Recomendado para | Compatibilidad amplia, CRUD simple | PS 8/9, arquitectura moderna, DI |
#Definir una entidad
src/Entity/MyEntity.php — entidad Doctrine
php
<?php
declare(strict_types=1);
namespace MyModule\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="ps_my_entity")
* @ORM\Entity(repositoryClass="MyModule\Repository\MyEntityRepository")
*/
class MyEntity
{
/**
* @ORM\Id
* @ORM\Column(name="id_my_entity", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private ?int $id = null;
/**
* @ORM\Column(name="name", type="string", length=255)
*/
private string $name = '';
/**
* @ORM\Column(name="active", type="boolean", options={"default": true})
*/
private bool $active = true;
/**
* @ORM\Column(name="date_add", type="datetime")
*/
private \DateTimeInterface $dateAdd;
public function __construct()
{
$this->dateAdd = new \DateTime();
}
// Getters
public function getId(): ?int { return $this->id; }
public function getName(): string { return $this->name; }
public function isActive(): bool { return $this->active; }
// Setters
public function setName(string $name): self { $this->name = $name; return $this; }
public function setActive(bool $active): self { $this->active = $active; return $this; }
}
#Instalar/desinstalar schema
mymodule.php — instalar y desinstalar tablas con SchemaTool
php
<?php
use Doctrine\ORM\Tools\SchemaTool;
public function install(): bool
{
return parent::install()
&& $this->registerHook('actionFrontControllerSetMedia')
&& $this->installEntities();
}
public function uninstall(): bool
{
$this->uninstallEntities();
return parent::uninstall();
}
private function installEntities(): bool
{
try {
$em = $this->get('doctrine.orm.entity_manager');
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(\MyModule\Entity\MyEntity::class),
$em->getClassMetadata(\MyModule\Entity\MyEntityLang::class),
];
$schemaTool->updateSchema($classes, true); // true = safe mode
return true;
} catch (\Throwable $e) {
$this->_errors[] = $e->getMessage();
return false;
}
}
private function uninstallEntities(): void
{
try {
$em = $this->get('doctrine.orm.entity_manager');
$schemaTool = new SchemaTool($em);
$classes = [
$em->getClassMetadata(\MyModule\Entity\MyEntity::class),
$em->getClassMetadata(\MyModule\Entity\MyEntityLang::class),
];
$schemaTool->dropSchema($classes);
} catch (\Throwable $e) {
// Log but don't block uninstall
}
}
#Acceder al Entity Manager
Acceder al EntityManager y operaciones CRUD
php
<?php
// Desde el modulo principal (acceso a container)
$em = $this->get('doctrine.orm.entity_manager');
// --- CREATE ---
$entity = new \MyModule\Entity\MyEntity();
$entity->setName('Mi entidad');
$entity->setActive(true);
$em->persist($entity);
$em->flush();
// $entity->getId() ahora tiene el ID generado
// --- READ ---
$repo = $em->getRepository(\MyModule\Entity\MyEntity::class);
$entity = $repo->find(42); // Por ID
$all = $repo->findAll(); // Todos
$active = $repo->findBy(['active' => true]); // Con filtro
$one = $repo->findOneBy(['name' => 'Mi nombre']); // Primero que coincide
// --- UPDATE ---
$entity->setName('Nuevo nombre');
$em->flush(); // No necesita persist si ya esta gestionado
// --- DELETE ---
$em->remove($entity);
$em->flush();
#Repositorios y queries
src/Repository/MyEntityRepository.php — queries personalizadas
php
<?php
declare(strict_types=1);
namespace MyModule\Repository;
use Doctrine\ORM\EntityRepository;
use MyModule\Entity\MyEntity;
class MyEntityRepository extends EntityRepository
{
/**
* Buscar entidades activas con paginacion.
*
* @return MyEntity[]
*/
public function findActivePaginated(int $page = 1, int $limit = 20): array
{
return $this->createQueryBuilder('e')
->where('e.active = :active')
->setParameter('active', true)
->orderBy('e.id', 'DESC')
->setFirstResult(($page - 1) * $limit)
->setMaxResults($limit)
->getQuery()
->getResult();
}
/**
* Busqueda por nombre con LIKE.
*/
public function searchByName(string $term): array
{
return $this->createQueryBuilder('e')
->where('e.name LIKE :term')
->setParameter('term', '%' . $term . '%')
->getQuery()
->getResult();
}
}
#services.yml — configuracion
config/services.yml — registrar el repositorio como servicio
yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: true
MyModule\:
resource: '../src/'
exclude:
- '../src/Entity/'
MyModule\Repository\MyEntityRepository:
factory: ['@doctrine.orm.entity_manager', 'getRepository']
arguments:
- MyModule\Entity\MyEntity
Descargar en Markdown
Pensado para pegar en ChatGPT, Claude u otra IA. Incluye solo el contenido de esta pagina.