Cómo usar múltiples bases de datos dinámicamente para un modelo en CakePHP
mysql multiple-databases (4)
Siempre puede consultar cualquier base de datos usando notación completa en mysql. F.ex .:
SELECT * FROM my_schema_name.table_name;
Forma de pastel:
$db = $this->getDataSource();
$query = array(
''fields'' => array(''*''),
''table'' => ''my_schema_name.table_name''
);
$stmt = $db->buildStatement($query, $this);
$result = $db->execute($stmt);
Ok, mi primera pregunta fue modificada tantas veces que decidí borrarla y reformular mi pregunta. He hecho un pequeño proyecto de caso de prueba con diferentes nombres de modelos para encontrar una solución adecuada para mi problema.
Advertencia : no mezcle las bases de datos con tablas
Motivación : separé los datos del usuario en múltiples bases de datos para cuestiones legales y de rendimiento.
Actualmente estoy trabajando en un proyecto CakePHP que tiene múltiples User
y cada User
tiene su propia base de datos con múltiples tablas ( cars
es una de las tablas ). Ahora, necesito explicar algo primero:
Cada User
tiene su propia base de datos (no una tabla, una base de datos ), por lo que los nombres de las bases de datos son los siguientes.
- Aplicación [DATABASE] (Esta es la base de datos principal de la aplicación)
- [TABLE]
users
-
permissions
[TABLE] ( No relevante para esta pregunta )
- [TABLE]
- [DATABASE]
app_user1
(User.id
1 posee esta base de datos completa)- [TABLE]
cars
(una tabla propiedad exclusiva deUser.id
1)
- [TABLE]
- [DATABASE]
app_user2
(User.id
2 posee esta base de datos completa)- [TABLE]
cars
(una tabla totalmente propiedad deUser.id
2)
- [TABLE]
- etc ...
Hice un pequeño dibujo que podría aclarar la base de datos / tabla -definiciones y sus relaciones con los modelos:
¡¡¡El problema!!!
No sé a qué base de datos me conectaré hasta que el User
inicie sesión. Los User
y sus bases de datos se crean dinámicamente, así que no puedo usar la app/Config/database.php
.
Por lo tanto, actualmente estoy escribiendo una extensión en las clases Model
y ConnectionManager
para eludir los comportamientos básicos de la base de datos de CakePHP. Entonces, el modelo de Car
sabe qué base de datos usar. ¡Pero tengo la sensación de que esto podría hacerse más fácilmente!
Así que supongo que todo se reduce a una pregunta:
¿Hay una manera más fácil de hacer esto?
¡Gracias a todos los que se tomarán el tiempo y el esfuerzo de leer y comprender mi problema!
No me gusta la idea de anotar el nombre real de la base de datos en el código. Para bases de datos múltiples, tiene el archivo database.php donde puede establecer tantas bases de datos como necesite.
Si desea "cambiar" una base de datos para un modelo específico sobre la marcha , use el método setDataSource . (ver aquí )
Por ejemplo, si tiene dos bases de datos, puede definirlas en el archivo database.php como "predeterminado" y "sandbox", como ejemplo.
Luego, en tu código:
$this->Car->setDataSource(''sandbox'');
La caja de arena es el nombre de la configuración, y el nombre real de la base de datos se escribe una sola vez en el archivo database.php.
En su database.php
public $mongo = array(
''datasource'' => ''Mongodb.MongodbSource'',
''database'' => ''database_name_mongo'',
''host'' => ''localhost'',
''port'' => 27017,
);
En tu controlador puedes usar
$this->Organisation->setDataSource(''mongo'');
luego aplica consulta como
this->Organisation->find(''all'');
¡Este caballero ( Olivier ) tenía el mismo problema! (Hace un año) ¡Escribió una pequeña adaptación para el Controller
s! Es bastante pequeño y resulta que funciona en 1.3 y 2.x.
De todos modos, esta es mi solución final, que puse en la app/Model/AppModel.php
:
class AppModel extends Model
{
/**
* Connects to specified database
*
* @param String name of different database to connect with.
* @param String name of existing datasource
* @return boolean true on success, false on failure
* @access public
*/
public function setDatabase($database, $datasource = ''default'')
{
$nds = $datasource . ''_'' . $database;
$db = &ConnectionManager::getDataSource($datasource);
$db->setConfig(array(
''name'' => $nds,
''database'' => $database,
''persistent'' => false
));
if ( $ds = ConnectionManager::create($nds, $db->config) ) {
$this->useDbConfig = $nds;
$this->cacheQueries = false;
return true;
}
return false;
}
}
Y así es como lo usé en mi app/Controller/CarsController.php
:
class CarsController extends AppController
{
public function index()
{
$this->Car->setDatabase(''cake_sandbox_client3'');
$cars = $this->Car->find(''all'');
$this->set(''cars'', $cars);
}
}
Apuesto que no soy el primero ni el último con este problema. Así que realmente espero que esta información encuentre personas y la comunidad de CakePHP.