Ok, ma première question a été modifiée tellement de fois que j'ai choisi de la supprimer et de reformuler ma question. J'ai mis au point un petit projet de test avec différents noms de modèles afin de trouver une solution appropriée à mon problème.
Avertissement: Ne mélangez pas les bases de données avec tables
Motivation: J'ai séparé les données de l'utilisateur en plusieurs bases de données pour les problèmes juridiques et de performance.
Je travaille actuellement sur un projet CakePHP comportant plusieurs User
name __ et dont User
a son propre base de données avec plusieurs tables _ (cars
est un de ses les tables). Maintenant, je dois d'abord expliquer quelque chose:
Chaque User
a son propre base de données (et non une table, un base de données), de sorte que les noms de base de données sont les suivants.
app
(Ceci est la base de données principale de l'application) users
_ permissions
( Non pertinent pour cette question )app_user1
(User.id
1 est propriétaire de tout ce base de données) cars
(a table entièrement détenue par User.id
1)app_user2
(User.id
2 est propriétaire de tout ce base de données) cars
(un table entièrement détenu par User.id
2)J'ai fait un petit dessin qui pourrait clarifier les base de données/table -finitions et leurs relations avec les modèles:
Le problème!!!
Je ne sais pas à quelle base de données se connecter jusqu'à ce que le User
se connecte. User
name __'s et leurs bases de données sont créés de manière dynamique; je ne peux donc pas utiliser app/Config/database.php
.
Donc j'écris actuellement une extension sur les classes Model
et ConnectionManager
pour contourner les comportements de base de la base de données de CakePHP. Donc, le modèle Car
sait quelle base de données utiliser. Mais j'ai juste le sentiment que cela pourrait être fait plus facilement!
Donc, je suppose que tout se résume à une question:
_ {Y a-t-il un moyen plus facile de faire cela?!} _
Merci à tous ceux qui prendront le temps et les efforts nécessaires pour lire et comprendre mon problème!
Ce monsieur ( Olivier ) avait le même problème! (Il y a un an) Il a écrit une petite adaptation pour les Controller
s! C'est assez petit et il s'avère que cela fonctionne dans 1.3 et 2.x .
Quoi qu’il en soit, c’est ma solution finale, que j’ai mise dans le 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;
}
}
Et voici comment je l'ai utilisé dans mon 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);
}
}
Je parie que je ne suis ni le premier ni le dernier avec ce problème. Donc, j'espère vraiment que cette information trouvera des personnes et la communauté CakePHP.
Je n'aime pas l'idée d'écrire le nom réel de la base de données dans le code. Pour plusieurs bases de données, vous avez le fichier database.php dans lequel vous pouvez définir autant de bases de données que nécessaire.
Si vous voulez "changer" de base de données pour un modèle spécifique à la volée , utilisez la méthode setDataSource . (voir ici )
Par exemple, si vous avez deux bases de données, vous pouvez les définir dans le fichier database.php comme "default" et "sandbox", à titre d'exemple.
Ensuite, dans votre code:
$this->Car->setDataSource('sandbox');
Le bac à sable est le nom de la configuration et le nom réel de la base de données n’est écrit qu’une fois dans le fichier database.php.
Vous pouvez toujours interroger toutes les bases de données en utilisant la notation complète dans mysql. F.ex .:
SELECT * FROM my_schema_name.table_name;
Façon de gâteau:
$db = $this->getDataSource();
$query = array(
'fields' => array('*'),
'table' => 'my_schema_name.table_name'
);
$stmt = $db->buildStatement($query, $this);
$result = $db->execute($stmt);
Dans votre database.php
public $mongo = array(
'datasource' => 'Mongodb.MongodbSource',
'database' => 'database_name_mongo',
'Host' => 'localhost',
'port' => 27017,
);
Dans votre contrôleur, vous pouvez utiliser
$this->Organisation->setDataSource('mongo');
puis appliquer une requête comme
this->Organisation->find('all');
Ceci est un peuple de la réponse acceptée. Cela empêchera l'erreur si la nouvelle source de données a déjà existé:
public function setDatabase($database, $datasource = 'default')
{
$newDatasource = $datasource . '_' . $database;
try {
// return the new datasource if it's already existed
$db = ConnectionManager::getDataSource($newDatasource);
$this->useDbConfig = $newDatasource;
$this->cacheQueries = false;
return true;
} catch (Exception $e) {
// debug($e->getMessage());
}
$db = ConnectionManager::getDataSource($datasource);
$db->setConfig(array(
'name' => $newDatasource,
'database' => $database,
'persistent' => false
));
if ( $ds = ConnectionManager::create($newDatasource, $db->config) ) {
$this->useDbConfig = $newDatasource;
$this->cacheQueries = false;
return true;
}
return false;
}