Categories: CakePHPTips

Modelos dinámicos en CakePHP

Últimamente estoy experimentando mucho con CakePHP y una de las cosas que he necesitado es crear unos modelos en los que pudiera cambiar en tiempo de ejecución la base de datos con la que están enlazados.

Básicamente estoy construyendo un portal en el que se aglutinan una serie de utilidades, y alguna de estas utilidades atacan a otras bases de datos independientes de portal.

Lo que se me ha ocurrido es crear en la base de datos del portal una tabla en la que almaceno la configuración de las bases de datos a las que quiero acceder (algunas de ellas comparten modelo). De esta manera puedo crear de manera dinámica las conexiones necesarias y enlazarlas con los modelos que necesite en ese momento.

La tabla es la siguiente:

CREATE TABLE databases (
  id int(11) unsigned NOT NULL AUTO_INCREMENT, 
  name varchar(20) NOT NULL DEFAULT '', 
  datasource varchar(255) NOT NULL DEFAULT 'Database/Mysql', 
  persistent tinyint(1) DEFAULT NULL, 
  host varchar(255) DEFAULT NULL, 
  login varchar(255) DEFAULT NULL, 
  password varchar(255) DEFAULT NULL, 
  database varchar(255) DEFAULT NULL, 
  prefix varchar(255) DEFAULT NULL, 
  encoding varchar(255) NOT NULL DEFAULT 'utf8', 
  PRIMARY KEY (id), 
  UNIQUE KEY name_UNIQUE (name) 
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

Y este sería uno de los modelos:

<?php
  App::uses('Model', 'Model');
  App::uses('ConnectionManager', 'Model');

  class EjemploUnoModel extends Model {
    public $useDbConfig = 'default';
    public $useTable = 'uno';
    public $primaryKey = 'clave';
    public $name = 'uno';
    public $hasMany = [
      'dos' => [
        'foreignKey' => 'clave',
        'associationForeignKey' => 'claveuno',
      ],
    ];

    public function __construct($id = false, $table = null, $ds = null) {
      if (isset($id['Database'])) {
        ConnectionManager::create($id['Database']['name'], $id['Database']);
        $this->useDbConfig = $id['Database']['name'];
        $id = false;
      }

      $this->dos->useDbConfig = $this->useDbConfig;
      $this->dos->useTable = 'dos';
      $this->dos->primaryKey = 'clavedos';
      $this->dos->name = 'dos';

      parent::__construct();
    }
  }

El ejemplo tiene también un enlace con otra tabla, en este caso llamada “dos”. En la documentación del CakePHP se explica que foreingKey es el campo de la tabla “uno” que realiza en enlace, y el associationForeignKey es el campo de la tabla “dos”. Para definir las propiedades relativas a la tabla “dos”, como el origen de datos (useDbConfig) lo hacemos en el constructor.

Y así es cómo lo utilizo:

App::uses('EjemploUnoModel', 'Model');
$database['Database'] = $this->Database->find('first', ['conditions' => ['name' => 'baseuno'], 'recursive' => -1]);
$uno = new EjemploUnoModel($database);
$lista = $uno->find('list', ['fields' => ['nombre'], 'recursive' => -1]);

El ejemplo hace una cosa un poco extraña

$database['Database'] = ...

esto es porque al ser un ejemplo he simplificado el esquema real de trabajo ya que tengo una tabla donde guardo los sistemas a los que voy a acceder y que está enlazada con la tabla databases que es donde se guardan las conexiones de las bases de datos… pero creo que se entiende.

alpha

Share
Published by
alpha
Tags: CakePHPPHP

Recent Posts

Apuntes de electrónica: Condensador y Bobina en alterna

Hace ya tiempo de mi última entrada de apuntes de electrónica. Fue la entrada sobre…

3 years ago

Review: Zoyi ZT-300AB Multimeter

Looking for cheap multimeters I found the Zoyi ZT-300AB, for about €20 we have a…

3 years ago

Zoyi multimeters, courtesy of Zotek Instruments

In my search for interesting multimeters I came across a manufacturer whose multimeters were sold…

3 years ago

Los productos remarcados

Desde que la industria empezó a deslocalizar sus fabricas llevando gran parte del peso de…

3 years ago

Análisis: Pinza amperimétrica Mestek CM83C

Desde que vi por primera vez una pinza amperimétrica quise tener una. Con la aparición…

3 years ago

Silencio

De lejos nos agobia, la distancia se hace notar con el silencio, de cerca es…

3 years ago