我在我的php项目中使用Redbeanphp(http://redbeanphp.com/)。我想为我的表使用表前缀。
自版本3.0以来,Redbeanphp不支持表前缀。但我想扩展Redbeanphp以支持我的项目中的表前缀。
我不想修改redbeanphp代码。但如果没有解决方案,我会这样做。
我已经尝试替换Redbeanphp的QueryWriter,但QueryWriter类并不总是相同(取决于我的数据库类型)。
最好的方法是什么?
答案 0 :(得分:6)
我现在得到了答复,所以我回答自己。
初始化redbean后,您可以配置新的工具箱。 redbean中的工具箱处理3个重要对象:查询编写器,Redbean OODB和数据库适配器。您可以使用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_QueryWriter_MySQL
Redbean查询编写器可能的类是:
所以,这是我的解决方案。我写了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始终在表名上使用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));
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::$writer
在configureFacadeWithToolbox
之后发生了变化,但由于某种原因,表名未被转换,我的自定义safeTable
函数中没有任何内容被执行。
如果您可以提供有关您如何测试方法或我可能缺少的更多信息,我很高兴听到它。
(对不起,这条消息不是你问题的答案,但我真的找不到任何其他方式向你发送消息或评论你的答案。该死的Stack Overflow!(开个玩笑,我喜欢它。))