Postgresql 在CakePHP中使用特定命令进行任何数据库访问之前

Postgresql 在CakePHP中使用特定命令进行任何数据库访问之前,postgresql,cakephp,connection,schema,Postgresql,Cakephp,Connection,Schema,我是CakePHP新手,使用的是1.3版 在执行任何数据库操作之前,如何动态更改数据库配置中的“schema”属性?在任何数据库交互之前,我可以在哪个类中执行postgres特定命令“将搜索路径设置为‘schema_xyz’” 我想利用Postgres在一个数据库中维护多个不同名称空间(Postgres术语中的模式)的能力,在我的应用程序中实现多租户。也就是说,每个名称空间将包含相同的表集,但显然具有不同的内容。在这里,重要的是不要将模式理解为意义,而是理解为模式是表容器的地方。准确的Postg

我是CakePHP新手,使用的是1.3版

在执行任何数据库操作之前,如何动态更改数据库配置中的“schema”属性?在任何数据库交互之前,我可以在哪个类中执行postgres特定命令“将搜索路径设置为‘schema_xyz’”

我想利用Postgres在一个数据库中维护多个不同名称空间(Postgres术语中的模式)的能力,在我的应用程序中实现多租户。也就是说,每个名称空间将包含相同的表集,但显然具有不同的内容。在这里,重要的是不要将模式理解为意义,而是理解为模式是表容器的地方。准确的Postgres命令并不重要。也就是说,是可以调用它的机制,并避开了Cake表描述的典型含义,如SchemaShell中所示。我发现Cake公开名称空间概念的唯一地方是database.php文件,该文件在首次建立DB连接时使用。请参阅:api13.cakephp.org/view_source/dbo postgres/#line-113(抱歉,新用户链接限制)

我想在所有DB查询之前设置该搜索路径,而不是像当前那样仅在连接时设置

作为概念证明,我尝试在模型中设置$useDbConfig,但根据打印SQL命令的调试输出,这似乎只影响所有查询的一个子集。我已经将其升级到app_model.php中,得到了相同的结果。通过动态创建一个db_config实例并通过loadDataSource传递给ConnectionManager来增强这一点。也许我应该在以前的所有版本中使用这些代码。。。方法

我在网上看到过许多帖子,其中人们讨论如何在database.php中使用几种数据库配置之一,以便在开发、实验室和生产环境中使用不同的数据库。但是我有一个具有多个名称空间/模式的数据库。此外,我的名称空间数量太多,太动态,无法在database.php中实现新变量的硬编码

因此,在CakePHP中,我可以在任何数据库命令之前插入一些东西来设置搜索路径的位置在哪里?我将在稍后处理优化问题。请记住,我是蛋糕新手,所以请尽量具体。如果我能澄清这个问题,请告诉我

提前谢谢。以下是部分工作的代码片段:

class AppModel extends Model {
  function beforeFind($queryData)
  {
    App::import("ConnectionManager");
    $cm = &ConnectionManager::getInstance();

    $namespace = 'xyz_namespace';            //name of the new schema/namespace/search path 
    $new_db_config_name = 'new_config';      //name for the new DB config to be used in the ConnectionManager
    $new_db_config = $cm->config->default; //copy the 'default' DB config into an array
    $new_db_config['schema'] = $namespace; //change/add the new schema/namespace/search path

    $cm->create($new_db_config_name, $new_db_config);   //turn the array into a DbConfig object
    $cm->loadDataSource($new_db_config_name);           //load the new DbConfig into the ConnectionManager
    $this->useDbConfig = $new_db_config_name;       //tell the model to new use the Db Config


    return $queryData;
  } 
}

如果我正确理解了您的问题,(恕我直言,我对Postgres知之甚少,但基本上我认为您的意思是,每当表透视图发生变化时重新加载模式?),下面介绍如何在控制器中动态切换模式:

// Model::getDataSource()->configKeyName holds whichever db config you're using
if ($this->Model->getDataSource()->configKeyName != 'default') {
    // do something...
    $this->loadModel("Special")
    $this->Model->table = "extras";
    $this->Model->schema(true);
} else {
    // predictably, Model::setDataSource($configKey) changes configs
    $this->Model->setDataSource("offsite"); // this could be a string variable
}
或者从模型中,
$this->getDataSource()->configKeyName
$this->schema(true)
等等。注意
$this->schema(true)
实际上会重新加载模型架构并将其注册到cake中。app_模型、组件或配置/引导可能是合适的位置。我不确定Cake第一次在哪里定义了search_路径,但它几乎肯定是dataSource对象的一个属性,可以像表名等一样在那里重新定义,然后重新加载Cake的模式以注册更改的路径。必须确保Cake卸载它可能已拾取的任何默认值,并根据当前定义的表加载正确的模式。(听起来这可能是你唯一错过的一步。)


如果这不能回答你的问题或者我误解了,请告诉我。HTH.:)

如果您想切换每个登录角色的模式,PostgreSQL中有一种非常简单的方法:

ALTER ROLE foo SET search\u path=bar,public;
ALTER ROLE baz SET search_path=bam,public;
因此,由该角色启动的连接会自动设置该搜索路径。
如果您的登录名与所需的模式名相同,则有一种更简单的方法,我引用:

如果其中一个列表项是特殊值$user,则架构 如果存在,则替换会话\用户返回的名称 这样的模式。(如果不是,则忽略$user。)

但请注意,再次:

特定于角色的变量设置仅在登录时生效;设定角色 和设置会话授权不处理特定于角色的变量 设置


我想你是在寻找cakeSchema和tableParameters部分的东西。希望对你有用you@api55-虽然很有趣,但我认为doc代码段指的是“表元数据”中的模式,而我指的是“名称空间”。我已经更新了我的帖子,希望澄清一下。我希望在任何DB命令之前执行的Psql命令是“将搜索路径设置为xyz”。这应该会影响整个数据库连接,而且它本身不是一个表参数。或者我只是不理解文档片段,这种情况经常发生。@JPBeaudry-你有没有弄明白这一点-我和你有相同的要求。我看不到已经提供的答案有什么帮助,因为您可能希望在会话期间切换到另一个模式。我也有同样的需要。谢谢恐怕我没有充分解释在Postgres中,“schema”一词有两种不同的含义(非常不幸)。因此,我更新了我的帖子。我不想如上所述重新加载模型模式。我想做的是,指示Postgres在下一个DB查询之前更改其“搜索路径”。假设同一个表在给定数据库中多次存在,但每个副本位于不同的命名空间中。Postgres使用搜索路径知道查询时将返回哪个副本。Erwin-当然,您是正确的。然而,我忘了提到,到目前为止,我只使用一个Postgres级别的用户。我最终会将其分为几个角色,但没有设想在每个应用程序用户的基础上这样做。根据CakePHP教程,网站中的登录/注销是通过存储在“users”DB表中的凭据来处理的
// Model::getDataSource()->configKeyName holds whichever db config you're using
if ($this->Model->getDataSource()->configKeyName != 'default') {
    // do something...
    $this->loadModel("Special")
    $this->Model->table = "extras";
    $this->Model->schema(true);
} else {
    // predictably, Model::setDataSource($configKey) changes configs
    $this->Model->setDataSource("offsite"); // this could be a string variable
}