Как динамически использовать несколько баз данных для одной модели в CakePHP
хорошо, мой первый вопрос был изменен так много раз, что я решил удалить его и переформулировать свой вопрос. Я сделал небольшой тестовый проект с разными именами моделей, чтобы найти правильное решение для моей проблемы.
предупреждение: не смешивать базы данных С таблицы
мотивация: я разделил пользовательские данные на несколько базы данных для юридических и производительность проблемы.
в настоящее время я работаю над CakePHP проект, который имеет несколько User
с каждого User
имеет база данных с множественными таблицы (cars
один из таблицы). Теперь мне нужно сначала кое-что объяснить:--22-->
User
свой база данных (не стол, а база данных), поэтому имена баз данных следует.
- [база данных]
app
(это основная база данных приложения )- [таблицы]
users
- [таблицы]
permissions
(не относится к этому вопросу)
- [таблицы]
- [база данных]
app_user1
(User.id
1 владеет всем этим база данных)- [таблицы]
cars
(a стол полностью принадлежитUser.id
1)
- [таблицы]
- [база данных]
app_user2
(User.id
2 владеет всем этим база данных)- [таблицы]
cars
(a стол полностью принадлежитUser.id
2)
- [таблицы]
- etc...
я сделал небольшой рисунок, который может разъяснить база данных / стол -определения и их отношение к моделям:
проблема!!!
я не знаю, что база данных для подключения до User
журналы. User
х и их базы данных создаются динамически, поэтому я не могу использовать app/Config/database.php
.
поэтому в настоящее время я пишу расширение на Model
и ConnectionManager
классы для обхода основных поведений базы данных CakePHP. Так что Car
модель не знает, который база данных использовать. Но я просто чувствую, что это можно сделать проще!
поэтому я думаю, что все сводится к одному вопрос:
есть ли более простой способ сделать это?!
спасибо всем, кто займет время и усилия, чтобы прочитать и понять мою проблему!
5 ответов
этот господин (Оливье) была такая же проблема! (Год назад) он писал: небольшая адаптация для Controller
s! Он довольно маленький, и оказывается, он работает в 1.3 и 2.x.
во всяком случае, это мое окончательное решение, которое я поместил в 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;
}
}
а вот как я использовал его в моем 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);
}
}
Я уверен, я не первый и не последний с этим проблема. Поэтому я очень надеюсь, что эта информация найдет людей и сообщество CakePHP.
мне не нравится идея записать фактическое имя базы данных в коде. Для нескольких баз данных у вас есть база данных.php-файл, где можно создать столько баз данных, сколько вам нужно.
Если вы хотите "переключить" базу данных для определенной модели на ходу используйте setDataSource метод. (см. здесь)
например, если у вас есть две базы данных, вы можете задать их в базе данных.php-файл как "по умолчанию" и "песочница", например.
затем, в коде:
$this->Car->setDataSource('sandbox');
песочница-это имя конфигурации, а фактическое имя базы данных записывается только один раз в базе данных.PHP-файл.
вы всегда можете запросить любые базы данных, используя полную нотацию в mysql. F. ex.:
SELECT * FROM my_schema_name.table_name;
торт так:
$db = $this->getDataSource();
$query = array(
'fields' => array('*'),
'table' => 'my_schema_name.table_name'
);
$stmt = $db->buildStatement($query, $this);
$result = $db->execute($stmt);
В вашей базе данных.в PHP
public $mongo = array(
'datasource' => 'Mongodb.MongodbSource',
'database' => 'database_name_mongo',
'host' => 'localhost',
'port' => 27017,
);
в вашем контроллере вы можете использовать
$this->Organisation->setDataSource('mongo');
затем применить запрос
this->Organisation->find('all');
это народ принятого ответа. Это предотвратит ошибку, если новый источник данных уже существует:
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;
}