Как динамически использовать несколько баз данных для одной модели в 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...

я сделал небольшой рисунок, который может разъяснить база данных / стол -определения и их отношение к моделям:

How to use multiple databases dynamically for one model in CakePHP

проблема!!!

я не знаю, что база данных для подключения до User журналы. Userх и их базы данных создаются динамически, поэтому я не могу использовать app/Config/database.php.

поэтому в настоящее время я пишу расширение на Model и ConnectionManager классы для обхода основных поведений базы данных CakePHP. Так что Car модель не знает, который база данных использовать. Но я просто чувствую, что это можно сделать проще!

поэтому я думаю, что все сводится к одному вопрос:

есть ли более простой способ сделать это?!

спасибо всем, кто займет время и усилия, чтобы прочитать и понять мою проблему!

5 ответов


этот господин (Оливье) была такая же проблема! (Год назад) он писал: небольшая адаптация для Controllers! Он довольно маленький, и оказывается, он работает в 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;
}