Cómo usar con Doctrine de PHP nombres de tablas dinámicos

2022-01-23 - Categorías: General / PHP / Symfony
Objetos relacionados base de datos

Este es un pequeño howto para darle una vuelta de tuerca al tema de los repositorios, Doctrine, nombres de tablas, Symfony, etcétera. Doctrine es un ORM que facilita mucho el manejo de los datos en BD. De casa viene configurado para usarse de forma que una tabla corresponde a una entidad, pero esto se puede hacer dinámico fácilmente.

Supongamos entonces que estamos usando una BD relacional Mysql, tenemos entonces que una entidad se asocia a una tabla. Y podemos tener el supuesto de que queramos dividir los datos en tablas por mes.

Para hacer esto a nivel de la Base de Datos, se podría hacer particionando la tabla, haciendo que aunque externamente desde el programa veamos sólo una tabla, internamente está particionada en varios ficheros. Otra opción podría ser tener una tabla por mes, directamente poniendo en el nombre de la tabla el mes (este es el objetivo de este post).

Cómo se hace con Doctrine

Con Doctrine se puede hacer de varias formas, entonces supongamos que estamos guardando información en un Log en un proyecto de pruebas de esos que todos tenemos. Podríamos hacer algo tal que así para guardar información creando tablas al vuelo, mediante el repositorio:

<?php

namespace App\Repository;

use App\Entity\Log;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

class LogRepository extends ServiceEntityRepository
{
    private $connection;
    private $year;
    private $month;

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Log::class);
        $this->connection = $this->getEntityManager()->getConnection();
        $this->year = date('Y');
        $this->month = date('m');
    }

    private function createTableIfNotExists()
    {
        $sql = "CREATE TABLE IF NOT EXISTS log$this->year$this->month (
        id INT(10) AUTO_INCREMENT PRIMARY KEY,
        ...;";
        $this->connection->executeQuery($sql);
    }

    public function saveSomething()
    {
        $this->createTableIfNotExists();

        $sql = "INSERT INTO log$this->year$this->month (...)
            VALUES (...);";

        $this->connection->executeQuery($sql);
    }

    public function saveSomethingElse($customMessage)
    {
        $this->createTableIfNotExists();

        $sql = "INSERT INTO log$this->year$this->month (...)
            VALUES ('$customMessage', ...);";

        $this->connection->executeQuery($sql);
    }
}

Otra forma, en EasyAdmin, para consultar con el CRUD controller una de las tablas en concreto, podría hacerse modificando lo que se llama el classMetadata:

    public function configureCrud(Crud $crud): Crud
    {
        $classMetadata = $this->entityManager->getClassMetadata(Log::class);
        $classMetadata->setPrimaryTable(['name' => 'log'.date('Y').date('m')]);

        return $crud
            ->setDefaultSort(['id' => 'DESC'])
            ->showEntityActionsAsDropdown(false)
        ;
    }

..esto mismo se puede hacer en cualquier otro controlador en un proyecto Symfony.

Otra forma es establecer en el constructor del repositorio, directamente el nombre de la tabla:

class LogRepository extends ServiceEntityRepository
{
    private $year;
    private $month;

    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Log::class);
        $this->connection = $this->getEntityManager()->getConnection();
        $this->year = date('Y');
        $this->month = date('m');

        $classMetadata = $this->getClassMetadata(Log::class);
        $classMetadata->setPrimaryTable([
            'name' => 'log'.$this->year.$this->month
        ]);
    }

Otra forma podría ser definiendo en variables de sesión $_SESSION, la tabla o mes que queremos usar. O podemos pasarlos por parámetros en el $_POST o en el $_GET.

Ya a partir de aquí es suma y sigue.

Recapitulando, no por usar Doctrine estamos casados a usar una entidad con una tabla necesariamente.

Me remito a este post anterior sobre el EasyAdmin para generar paneles de control para Symfony. También te puede interesar este otro sobre iniciación a Symfony.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

 

© 2022 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.