代码之家  ›  专栏  ›  技术社区  ›  Strae

PHP OOP困境:如何在类对象中保持数据库连接?

  •  2
  • Strae  · 技术社区  · 16 年前

    我正在开发(嗯,我还在计划阶段)一个web应用程序,我会让其他开发者有可能编写自己的插件/模块(就像CMS、drupal、joomla等)。

    我的问题是我必须 由于许多原因(首先是数据完整性),开发人员不得不使用我为与数据库交互而编写的方法。我不需要对数据库结构保密,但如果可能的话,我很感激。

    总之,我的目标是:

    1. 保持“受保护”且不可从我的类外部访问数据库连接;
    2. 如果可能(但应该是第1点的结果),对真实的数据库结构保密;

    下面是我目前处境的一个简短例子:

    <?php
        // File dbclass.php
    class DbHandler{
        /*
        * As simply as i could ;)
        */
        private $dbLink;
        public function __construct(){
            $this->dbLink = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
        }
        public function __destruct(){
            pg_close($this->dbLink);
            unset($this->dbLink);
        }
    }
    ?>
    

    以及模块调用:

    <?php
    // An general situation
    require('dbclass.php');
    /*
    * The DbHandler consctruct function open a database connection.
    */
    $init = new DbHandler();
    /*
    * [..i'll do something here..]
    */
    /*
    * Lets say this is inside a function/hook of an enabled module;
    * This is the behavior i want to avoid!
    * How to keep the database connection 'within' my
    * DbHandler object's instance?
    * p.s: in real life i do use prepared stmt
    */
    $qrUsers = pg_query('SELECT * FROM users');
    if(pg_num_rows($qrUsers) != 0){
        echo '<h2>Query success!</h2>';
        //do something
    }else{
        echo '<h2>Query Fail!</h2>';
    }
    //Actual Output: Query Success! [...]
    //Desidered output: Warning: pg_query() [function.pg-query]: No PostgreSQL link opened yet in /var/www-lighttpd/dbtest.php on line xx Query Fail!
    ?>
    

    我希望,如果开发人员试图直接执行一个查询,它将失败,在我发布的示例中,他被迫使用如下方法(例如)

    $users = new User();
    $users -> get_all();
    

    就我所想,这个 我能做的就是关闭连接 之前

    如果有人有更好的想法,请与我分享!

    编辑 鬼连接 runkit / apd

    5 回复  |  直到 16 年前
        1
  •  1
  •   Oddthinking    16 年前

    这有点像黑客,但是:

    在进行pg_connect调用后,可以立即使用一些无用参数调用pg_connect。它将失败,但请查看它是否也覆盖默认连接,以防止其他人在pg_查询中使用它。。

    编辑

    以下是计划B(未经测试):

    $this->dbLink = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
    $junkConnection = pg_connect("host=127.0.0.1 user=myuser password=mypassword dbname=mydatabase");
    pg_close($junkConnection);
    

    这将创建到数据库的第二个连接,但会立即将其关闭。我严重怀疑这会使默认参数恢复到第一个连接。

        2
  •  3
  •   oops    16 年前

    我想到了两个选择:

    1. pg_*

    黑客喜欢打开/关闭虚拟DB连接将工作,但我会认为这是一个最后的手段。

    听起来您希望确保系统及其插件的质量。我认为这些黑客无法达到这个目的。毫无疑问,我在这里做了一些假设,但总的来说,我认为最好的方法是向插件作者提供可靠的示例/标准和良好的文档。如果您将为这些插件托管一个权威存储库,那么您还可以扫描它们的代码,查看是否存在这样的违规行为,并建议维护人员修复它们。

        3
  •  0
  •   moritz    16 年前

    decorator pattern ,这可能适合您的需要。其思想是实际创建数据库对象的代理实例,其行为与实际数据库完全相同。因此,真实数据库对其他人是隐藏的,只有装饰器对象知道在哪里可以找到真实数据库。

        4
  •  0
  •   0scar    16 年前

    嗯,也许你可以在DB级别解决这个问题?

    app-main 或者你联系到的,没有特权的,叫做 app-plugin . 然后,您可以这样调用您的插件:

    pg_query("SET ROLE app-plugin;"); //precaution--use low-privilege-user
    $plugin->doStuff();
    pg_query("SET ROLE NONE;"); //Reset role back to default
    

    应用程序插件 SET ROLE NONE; 重新获得特权,所以不“安全”。这只是一种预防措施。但连接至少会保持活动状态,正常查询将失败(当然,如果插件在一个会话中被调用50次,可能会影响性能。。谁知道呢?)

    无论如何,我从来没有尝试过这个mysqlf,所以我对此一无所知,真的。。

    文件:
    http://www.postgresql.org/docs/8.4/interactive/sql-set-role.html

        5
  •  -1
  •   Community Mohan Dere    6 年前

    我可能错过了什么,但是 只要用户可以阅读您的代码,他们就可以复制&粘贴建立自己连接所需的信息 . 你真的允许用户连接到你的数据库吗?!

    假设它位于已启用模块的函数/挂钩内;

    这是我想要避免的行为!

    选择*。。。

    这不是你的问题。我猜用户将在他们自己的环境/数据库中托管你的应用程序,因此,当你提供更好的替代方案时,他们会受到不良做法的损害。