redbeanphp和表前缀

时间:2013-01-03 10:04:17

标签: php orm redbean

我在我的php项目中使用Redbeanphp(http://redbeanphp.com/)。我想为我的表使用表前缀。

自版本3.0以来,Redbeanphp不支持表前缀。但我想扩展Redbeanphp以支持我的项目中的表前缀。

我不想修改redbeanphp代码。但如果没有解决方案,我会这样做。

我已经尝试替换Redbeanphp的QueryWriter,但QueryWriter类并不总是相同(取决于我的数据库类型)。

最好的方法是什么?

3 个答案:

答案 0 :(得分:6)

我现在得到了答复,所以我回答自己。

初始化redbean后,您可以配置新的工具箱。 redbean中的工具箱处理3个重要对象:查询编写器,Redbean OODB和数据库适配器。您可以使用R::$toolbox

访问当前的redbean工具箱

您可以执行以下代码:

R::configureFacadeWithToolbox(new RedBean_ToolBox(R::$redbean, R::$adapter, R::$writer));

此代码不执行任何操作。因为您使用新工具箱配置Redbean但具有相同的OODB,相同的数据库适配器和相同的查询编写器。但是在这段代码中,您可以用自己的对象替换其中一个对象。

示例,用虚拟编写器替换编写器:

$writer = new MyQueryWriter();
R::configureFacadeWithToolbox(new RedBean_ToolBox(R::$redbean, R::$adapter, $writer));

探针如下:

  • 您希望用自己的查询编写器替换查询编写器来处理表前缀
  • 查询编写器类并不总是相同。 Redbean为查询编写器使用5个类。该类取决于数据库类型。例如,如果使用Mysql数据库,则查询编写器类为RedBean_QueryWriter_MySQL
  • 您不想编写整个查询编写器。

Redbean查询编写器可能的类是:

  • RedBean_QueryWriter_CUBRID
  • RedBean_QueryWriter_MySQL
  • RedBean_QueryWriter_Oracle
  • RedBean_QueryWriter_PostgreSQL
  • RedBean_QueryWriter_SQLiteT

所以,这是我的解决方案。我写了5个小课程。

class MyCubridQueryWriter extends RedBean_QueryWriter_CUBRID {

   public function safeTable($name, $noQuotes = false) {
      $name = prefix($name);
      return parent::safeTable($name, $noQuotes);
   }

} 

class MyMysqlQueryWriter extends RedBean_QueryWriter_MySQL {

   public function safeTable($name, $noQuotes = false) {
      $name = prefix($name)
      return parent::safeTable($name, $noQuotes);
   }

}

class MyOracleQueryWriter extends RedBean_QueryWriter_Oracle {

   public function safeTable($name, $noQuotes = false) {
      $name = prefix($name)
      return parent::safeTable($name, $noQuotes);
   }

} 

class MyPostgreSqlQueryWriter extends RedBean_QueryWriter_PostgreSQL {

   public function safeTable($name, $noQuotes = false) {
      $name = prefix($name)
      return parent::safeTable($name, $noQuotes);
   }

}

class MySQLiteTQueryWriter extends RedBean_QueryWriter_SQLiteT {

   public function safeTable($name, $noQuotes = false) {
      $name = prefix($name)
      return parent::safeTable($name, $noQuotes);
   }

} 

如您所见,每个类都扩展了一个Redbean查询编写器类。我们覆盖了safeTable方法。 Redbean始终在表名上使用safeTableprefix功能很简单:

function prefix($table) {
    return "my_prefix_$table";
}

现在,在我们的代码中。我们可以使用数组将Redbean查询编写器类映射到我们自己的类并替换它。我们在这里:

$writerMapping = array(
    'RedBean_QueryWriter_CUBRID' => 'MyCubridQueryWriter',
    'RedBean_QueryWriter_MySQL' => 'MyMysqlQueryWriter',
    'RedBean_QueryWriter_Oracle' => 'MyOracleQueryWriter',
    'RedBean_QueryWriter_PostgreSQL' => 'MyPostgreSqlQueryWriter',
    'RedBean_QueryWriter_SQLiteT' => 'MySQLiteTQueryWriter'
);

$class = $writerMapping[get_class(R::$writer)];
$writer = new $class(R::$adapter);

R::configureFacadeWithToolbox(new RedBean_ToolBox(R::$redbean, R::$adapter, $writer));

Et瞧。现在Redbean将使用你自己的作家,你可以做你想做的!使用我们的safeTable方法,我们为数据库中的每个表名添加前缀。

答案 1 :(得分:0)

我想在使用WordPress时使用RedBean时遇到了这个问题。我的解决方案是创建另一个类(“wordpress redbean”的WPR),如下所示:

class WPR {

    public static function __callStatic($method, $params)
    {
        global $wpdb;
        $prefix = $wpdb->base_prefix;

        foreach ($params as &$param)
            $param = preg_replace('/\{([a-zA-Z0-9_]+)\}/', $prefix . '$1', $param);

        // switch to wordpress database
        R::selectDatabase('WPR');

        // do the dang thing
        $res = call_user_func_array(array('R',$method),$params);

        // go back
        R::selectDatabase('default');

        // send it
        return $res;
    }
};

R::addDatabase('WPR', "mysql:host=".DB_HOST.";dbname=".DB_NAME, DB_USER, DB_PASSWORD);

我也希望这个类使用与我的'常规'redbean类不同的数据库,所以我在那里调用了selectDatabase()。如果你不需要它们,请评论它们。

它的作用是作为redbean的代理,但是每次输入都会检查像{this}这样的子字符串,并将其扩展为带有前缀的完整数据库名称。以下是您的使用示例:     $my_blog = WPR::find('{blogs}', 'domain=?', array('mydomain.com'));或     $allowed_hosts = WPR::getCol('SELECT domain FROM {blogs}');

在这两种情况下,{blogs}会转换为wp_blogs

答案 2 :(得分:0)

新空气,

我和你有同样的问题。我尝试了你的解决方案,但无法使其正常工作。我写了几个函数用于前缀和我的对象名称到表名和后面,我认为这将在我的情况下工作,但我仍然希望让你的方式工作,因为它会更透明。我有没有前缀的表名,用于阅读和写作。

我注意到在RedBean中没有开箱即用的Oracle支持,所以我添加了对每个类名的检查以避免错误:

if (class_exists('RedBean_QueryWriter_MySQL', false)) {
    class MyMysqlQueryWriter extends RedBean_QueryWriter_MySQL {
    ...
}

检查应该有效,在加载前缀代码时,我输出到我的MySQL(我正在使用)块中的日志。

此外,最后你写道:

$class = $writerMapping(get_class(R::$writer));

但你可能意味着:

$class = $writerMapping[get_class(R::$writer)];

根据一些调试,我的R::$writerconfigureFacadeWithToolbox之后发生了变化,但由于某种原因,表名未被转换,我的自定义safeTable函数中没有任何内容被执行。

如果您可以提供有关您如何测试方法或我可能缺少的更多信息,我很高兴听到它。

(对不起,这条消息不是你问题的答案,但我真的找不到任何其他方式向你发送消息或评论你的答案。该死的Stack Overflow!(开个玩笑,我喜欢它。))