【问题标题】:redbeanphp and table prefixredbeanphp 和表前缀
【发布时间】:2012-12-17 16:19:35
【问题描述】:

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

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

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

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

最好的方法是什么?

【问题讨论】:

    标签: php orm redbean


    【解决方案1】:

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

    redbean 初始化后,就可以配置新的工具箱了。 redbean 中的工具箱处理 3 个重要对象:查询编写器、Redbean OODB 和数据库适配器。你可以通过R::$toolbox访问当前的redbean工具箱

    你可以做这个代码:

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

    这段代码什么都不做。因为您使用新工具箱配置 Redbean,但使用相同的 OODB、相同的数据库适配器和相同的查询编写器。但在这段代码中,您可以将其中一个对象替换为您自己的对象。

    例如,将 writer 替换为 dummy writer:

    $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 总是在表名上使用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));
    

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

    【讨论】:

    • @Eiskis 你应该创建一个新的 redbean 实例作为 RedBean_ToolBox 的第一个参数:R::configureFacadeWithToolbox(new RedBean_ToolBox(new RedBean_OODB($writer), R::$adapter, $writer));
    • safeTable 已被贬低以支持使用 esc,问题是它使用相同的功能转义了列名和表名。这意味着如果您覆盖 esc,所有列也将获得前缀。
    【解决方案2】:

    我想在 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

    【讨论】:

      【解决方案3】:

      魔法师,

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

      我注意到 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)];
      

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

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

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

      【讨论】:

      • 哦,是的,你是对的,我的代码有错误。我更正了。但我的解决方案对我有用,每次 redbean 需要生成表名(写入、读取和创建表)时,redbean 都会调用我的查询编写器的 safeTable 方法。
      • 能否添加用于创建连接并执行读/写操作的代码?也许这里有一些必不可少的东西。
      • 代码非常具体,所以我把代码放在了一个 pastebin 中:pastebin.com/gWJubPDd 这个代码来自我的一个项目。你可以在这里找到整个课程和项目:github.com/dreignier/metalizer/blob/master/www/metalizer/util/…
      • 非常感谢,我去看看。我正在将此集成到现有解决方案中,如果我发现任何有趣或需要关注的事情,我会回复您。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多