【问题标题】:PHP/MySQL isolating database access in a class - how to handle multiple row result set in an OOP mannerPHP/MySQL 隔离类中的数据库访问——如何以 OOP 方式处理多行结果集
【发布时间】:2009-08-27 15:27:01
【问题描述】:

类中的PHP/MySQL隔离数据库访问——如何处理多行选择

这是一个编码问题。 我隔离了一个类中的所有数据库访问函数

<?php
class DB {
    var $conn;         
    function DBClass () {
                @$this-> conn = mysqli_connect (DB_SERVER, DB_USER, DB_PASS, DB_NAME);
    }
    function validateUser ($aUserid, $aPassword) {
                …  validation code – sql injection code etc..
                $sql = "Select userid, name, level From users where userid = '$aUserid' and password = '$aPassword'";
                $result = mysqli_query ( $this->conn, $sql );
                if (!$result || (mysqli_num_rows ($result) < 1)) {
                            return false;
                }
                $dbarray = mysqli_fetch_assoc ($result); // get a row
                return $dbarray;
    }

    function getProduct ($aProductid) {

                return $dbarray;
    }

    function getProductList () {  
                // <----------- this would be the problem function
    }
}

$DB = new DBClass();
?>

我的调用例程:

<?php
        $dbarray = $DB->validateUser ($_POST['userid'], $_POST['password']); 
?>

没问题,它工作正常。我遇到了超过一行的结果集的问题。现在我必须回到每一行的类对象。如果我在调用例程中包含 MySQL 代码没问题,但我想将它隔离在我的类中,我不知道如何编写它。

有什么想法吗?有什么例子吗?

【问题讨论】:

    标签: php mysql oop coding-style


    【解决方案1】:

    如果你使用 PHP 5.3.0 和 mysqlnd,你可以使用新函数mysqli_fetch_all()。这将返回一个关联数组的数组。

    如果您使用的是早期版本的 PHP,您可以切换到使用 PDO,并使用函数PDOStatement::fetchAll()

    您在评论中询问一个非常大的结果集怎么样。确实,无限的结果集可能会导致数组超出 PHP 内存限制,这会导致致命错误并停止脚本。但这真的是个问题吗?你有多少产品?您可以使用LIMIT 来确保查询不是无限的。


    关于重返课堂的另一部分问题,我建议开设 Iterator 课堂:

    class DB implements IteratorAggregate
    {
      protected $_data = array();
    
      public function getProductList() {
        // fetch all results from SQL query, stuff them into $this->_data
        return $this->getIterator();
      }
    
      public function getIterator() {
        return new ArrayIterator($this->_data);
      }
    }
    

    现在您可以在foreach 循环中使用该类:

    $db = new DB();
    foreach ($db->getProductList() as $product) {
      // do something with each product
    }
    

    IteratorAggregate 接口意味着您甚至可以这样做:

    $db = new DB();
    $db->getProductList();
    // ...other steps...
    foreach ($db as $product) {
      // do something with each product
    }
    

    当然,使用此方法一次只能存储一个结果集。如果您同时将 DB 类用于任何其他查询,这会使事情变得复杂。出于这个原因,大多数人不会尝试编写单个类来封装所有数据库操作。他们为需要使用的每种类型的Domain Model 编写单独的类,与数据库连接分离。

    【讨论】:

    • 谢谢比尔,这非常有用。我尝试了 mysqli_fetch_all() 并得到了一个未知的函数错误。我最近安装了 XAMPP,所以我相信我有最新版本。我需要做些什么来激活 mysqlnd 吗?再次感谢
    • 根据文档,该函数依赖于 PHP 5.3.0 和 mysqlnd 驱动程序。您应该能够使用phpinfo() 找出您拥有的版本和扩展。
    • 啊,你是对的。我刚刚检查了 XAMPP 1.7.1 使用 php 5.2.9 XAMPP 1.7.2 最近发布(8 月 10 日)使用 PHP 5.3.0,但没有更新包。所以我要么等待,要么卸载并安装 1.7.1。再次感谢。我原来的问题确实有一个与oop相关的潜台词,也就是说,如果你需要回到一个类来从之前调用的类函数中获取额外的数据,你会怎么做?
    • 再次感谢比尔。迭代器类很好。我不知道它存在。很高兴找到一个不仅有答案,而且理解问题的人。
    • 是的,IteratorAggregate 是称为 SPL 的 PHP 扩展的一部分。 SPL 的开发人员完全不明白他们需要编写文档。我与 SPL 项目负责人交谈,并提出帮助编写文档,他说:“当然,我们需要有人编写构建脚本,以便从代码中自动生成文档。”
    【解决方案2】:

    您可以将结果保存在数组中并返回:

    function getProductList () {
       $sql = "SELECT ...";
       $result = mysqli_query ( $this->conn, $sql );
    
       $myProducts = array();
    
       while ($row = mysqli_fetch_assoc($result))
          $myProducts[] = $row; // or array_push($myProducts, $row)
       }
    
       return $myProducts
    }
    

    因此,您将拥有一个数组数组,其中的每个元素将包含一行结果。

    【讨论】:

    • 谢谢,这会奏效。对于一个非常大的结果集,对于数组来说太大了,你会建议什么?
    • 您可以将结果存储在一个新的类成员 var 中并编写一个获取下一行的函数。也许创建一个处理结果的新类?
    【解决方案3】:

    您的登录页面中有一个 SQL 注入。

    如果有人输入密码会发生什么: xxx' 或 'yyy' 'x

    【讨论】:

    • 我没有展示处理验证的代码,因为它与我的问题无关。我只验证字母和数字的字段。我不允许特殊字符。我允许以 O'reilly 的名字命名。如果我要允许特殊字符,那么我将不得不更加小心并以不同的方式对其进行编码。一种方法是使用 sql Prepare。 function validateUser ($aUserid, $aPassword) { HERE->> ... 验证码 – sql 注入代码等。$sql = "Select userid, name, level From users where userid = '$aUserid' and password = '$aPassword' ";
    猜你喜欢
    • 2016-09-20
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 2021-05-19
    • 1970-01-01
    • 2014-01-11
    • 2012-08-21
    • 2014-11-10
    相关资源
    最近更新 更多