web-dev-qa-db-ja.com

CakePHPの1つのモデルに対して複数のデータベースを動的に使用する方法

わかりました。最初の質問は何度も変更されたため、削除して質問を再定式化することにしました。問題の適切な解決策を見つけるために、さまざまなモデル名で小さなテストケースプロジェクトを作成しました。

警告データベーステーブルを混在させないでください

動機:法的な問題とパフォーマンスの問題のために、ユーザーデータを複数に分割しましたデータベース

現在、私は複数のUserを持つCakePHPプロジェクトに取り組んでおり、各Userには独自のデータベース複数のテーブルcarsテーブルの1つです)。今、私は最初に何かを説明する必要があります:

すべてのUserには独自のデータベース(テーブルではなく、データベース)があるため、データベース名は次のようになります。

  • [データベース] app(これはアプリのメインデータベースです)
    • [表] users
    • [表] permissionsこの質問には関係ありません
  • [データベース] app_user1User.id 1はこの全体を所有していますデータベース
    • [TABLE] cars(a table完全にUser.id 1が所有)
  • [データベース] app_user2User.id 2はこの全体を所有していますデータベース
    • [テーブル] cars(a テーブル完全にUser.id 2が所有)
  • 等...

データベース/テーブル-定義とそれらのモデルとの関係を明確にする可能性のある小さな図面を作成しました。

How to use multiple databases dynamically for one model in CakePHP

問題!!!

Userがログインするまで、どのdatabaseに接続するかわかりません。Userとそのdatabasesは動的に作成されるため、 app/Config/database.phpを使用できません。

そのため、私は現在、ModelクラスとConnectionManagerクラスに拡張機能を記述して、CakePHPの基本的なデータベースの動作をバイパスしています。したがって、Carモデルは、使用するデータベースを認識しています。しかし、私はこれがもっと簡単にできると感じています!

だから私はそれがすべて1つの質問に要約されると思います:

これを行う簡単な方法はありますか?!

私の問題を読んで理解するために時間と労力を費やしてくれる人に感謝します!

16
Ariaan

この紳士オリビエ )も同じ問題を抱えていました! (1年前) 彼は書いたControllersの小さな適応!それはかなり小さく、1.32.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コミュニティを見つけることを本当に望んでいます。

38
Ariaan

データベースの実際の名前をコードに書き留めるという考えは好きではありません。複数のデータベースの場合、必要な数のデータベースを設定できるdatabase.phpファイルがあります。

特定のモデルのデータベースをオンザフライで「切り替える」場合は、setDataSourceメソッド。 ( ここ を参照)

たとえば、2つのデータベースがある場合、例として、database.phpファイルでそれらを「default」と「sandbox」として定義できます。

次に、コードで:

$this->Car->setDataSource('sandbox');

サンドボックスは構成の名前であり、データベースの実際の名前はdatabase.phpファイルに1回だけ書き込まれます。

9
noamicko

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);
1
bancer

Database.phpで

public $mongo = array(
    'datasource' => 'Mongodb.MongodbSource',
    'database' => 'database_name_mongo',
    'Host' => 'localhost',
    'port' => 27017,
);

あなたのコントローラーであなたは使うことができます

$this->Organisation->setDataSource('mongo');

次に、次のようなクエリを適用します

this->Organisation->find('all');
1
teju c

これは受け入れられた答えの人々です。これにより、新しいデータソースがすでに存在する場合にエラーを防ぐことができます。

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;
}
0
trank