4

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

Redbeanphp 从 3.0 版本开始不支持表前缀。但我想扩展 Redbeanphp 以在我的项目中支持表前缀。

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

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

最好的方法是什么?

4

3 回答 3

7

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

一旦redbean被初始化,你就可以配置一个新的工具箱。redbean 中的工具箱处理 3 个重要对象:查询编写器、Redbean OODB 和数据库适配器。您可以使用以下命令访问当前的 redbean 工具箱R::$toolbox

您可以执行以下代码:

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个littles类。

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 总是safeTable在一个表名上使用。prefix功能很简单:

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

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

于 2013-01-03T20:01:56.687 回答
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

于 2013-01-04T22:28:52.603 回答
0

魔术师,

我和你有同样的问题。我尝试了您的解决方案,但无法正常工作。我编写了几个函数,用于将我的对象名称添加到表名中并返回,我认为这在我的情况下会起作用,但我仍然想让你的方式工作,因为它会更加透明。我有用于读写的无前缀表名。

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

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)];

根据一些调试, myR::$writer之后发生了更改configureFacadeWithToolbox,但是,由于某种原因,表名没有被转换,并且我的自定义safeTable函数中没有任何内容正在执行。

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

(很抱歉,这条消息不是您问题的答案,但我真的找不到任何其他方式向您发送消息或评论您的答案。该死的堆栈溢出!(开个玩笑,我喜欢它。) )

于 2013-01-07T19:14:21.817 回答