【问题标题】:What is the equivalent of bind_result on PDOPDO 上的 bind_result 等价物是什么
【发布时间】:2013-09-09 20:47:30
【问题描述】:

我正在转换为 PDO 并使用准备好的语句,我想将我的结果绑定为 $stmt->bind_result($email_count); 所以我可以将其放入 if 语句中以查看电子邮件是否存在但是我得到了与前面的示例相关的错误Fatal error: Call to undefined method PDOStatement::bind_result() in /Applications/XAMPP/xamppfiles/htdocs/imanage/insert.php on line 51

我猜 bind_result 不是 PDO 定义的方法,那么我可以使用等效的方法吗?

我的代码如下以防万一:

插入.php

<?php

 include("connect/class.Database.php");

 class Users extends Database {

     public function insert() {

            $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM users WHERE email=:email");
            $stmt->bindParam(":email", $_POST['email']);
            $stmt->bind_result($email_count);
            $stmt->execute();
            $stmt->fetch(PDO::FETCH_ASSOC);

                    if ($email_count > 0) {
                        echo "email exisits! click here to try <a href='register'>again</a>";
                        } else {
                            //escape the POST data for added protection
                            $username = isset($_POST['username']) ? $_POST['username'] : null;
                            $cryptedPassword = crypt($_POST['password']);
                            $password = $cryptedPassword;
                            $name = isset($_POST['name']) ? $_POST['name'] : null;
                            $email = isset($_POST['email']) ? $_POST['email'] : null;

                            $data = array($username, $password, $name, $email); 
                            $stmta = $this->pdo->prepare("INSERT INTO users (username, password, name, email) VALUES (?, ?, ?, ?)");
                            $stmta->execute($data);

                                printf("%d Row inserted.\n", $stmta->row_count);
                                /* close statement and connection */
                                $stmta->close();
                } // end email_count and insert to table
            } // end function

      }
?>

连接/class.Database.php

<?php

// Database connection PDO

class Database {

    public function __construct() {
        // Connection information
        $host   = 'localhost';
        $dbname = 'imanage';
        $user   = 'root';
        $pass   = '';

        // Attempt DB connection
        try
        {
            $this->pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            echo 'Successfully connected to the database!';
        }
        catch(PDOException $e)
        {
            echo $e->getMessage();
        }

    }

     public function __destruct()
    {
        // Disconnect from DB
        $this->pdo = null;
        echo 'Successfully disconnected from the database!';
    }


}

?>

【问题讨论】:

  • bind_result 看起来像一个 MySQLi 函数:php.net/manual/en/mysqli-stmt.bind-result.php 这意味着您不可能将 pdo 函数与 MySQLi 混合和匹配,反之亦然。
  • $stmt-&gt;fetch(PDO::FETCH_ASSOC) 返回一个关联数组,这与 mysqli 调用中的 fetch() 不同,后者需要变量引用。您可以只获取由$row = $stmt-&gt;fetch(PDO::FETCH_ASSOC) 之类的调用返回的数组来查看您得到了什么,print_r($row);
  • 这就是绑定在 PDO 中的工作方式:php.net/manual/en/pdostatement.bindparam.php(另请查看该页面上的其他绑定函数)
  • 查看PDOStatement::fetch() docs for examples...它通常比 MySQLi 更容易使用。
  • 好的,谢谢,但是我如何存储电子邮件的计数?以便我可以提醒用户此电子邮件已存在? @MichaelBerkowski

标签: php mysql pdo


【解决方案1】:

您根本不需要带有 PDO 的丑陋 bind_result。

但你也不需要计算。请避免不必要的操作 - 它们只会无缘无故地膨胀和混淆您的代码。

首先想一想,您需要从查询中得到什么?你真的需要数数吗?不,您真正需要的只是一个标志 - 如果用户存在或不存在。因此,进行查询以返回这样的标志。

$stmt = $this->pdo->prepare("SELECT 1 FROM users WHERE email=?");
$stmt->execute(array($_POST['email']));
$exists = $stmt->fetchColumn();

代码的所有其他部分也是如此

//escape the POST data for added protection

您实际上并没有“转义”此代码块中的任何数据,也没有添加任何保护。然而,我认为将 NULL 作为电子邮件插入绝对没有意义。你确定你真的想要吗?

【讨论】:

  • @YourCommonSense 这行现在是多余的吗$stmta-&gt;close();?还是查询会自动关闭?
  • @YourCommonSense,我在 $email = isset($_POST['email']) 行上也有 null 吗? $_POST['email'] : null;因为在 mysqli 准备好的语句上没有这个,它没有正确插入数据,它插入的是一个数值而不是实际值
  • @gutigrewal 最多只返回一行的语句,将在第一次 fetch 操作后自动关闭,所以是的,在这种情况下使用 $stmt-&gt;closeCursor() 是多余的
  • @gutigrewal 大多数时候你不必费心。如果您有一个运行查询并返回结果的专用方法 - 关闭将是一个好习惯。但只要您使用的是原始 PDO - 不要打扰。
  • @gutigrewal 说这些 NULL - 你肯定会混淆一些东西。说 od DB 连接 - 主要思想是每个应用程序只有 ONE 连接。你用哪种方式实现它并不重要。但是你必须确保你只连接一次
【解决方案2】:

要快速从SELECT COUNT() 查询中检索值,请查看PDOStatement::fetchColumn,例如

$stmt = $pdo->prepare('SELECT COUNT(1) FROM users WHERE email = :email');
$stmt->bindParam(':email', $email);
$stmt->execute();
$email_count = $stmt->fetchColumn();

我还想提供一些进一步的建议。您不应该在类构造函数中创建PDO 连接。这意味着每次实例化扩展Database 的类时,都会创建一个新连接。相反,将PDO 实例作为依赖项传递,例如

abstract class Database {
    /**
     * @var PDO
     */
    protected $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }
}

User::insert 方法也是如此。尝试通过方法参数传递任何必需的参数。如果您想开始为您的课程编写单元测试,这将是非常宝贵的

public function insert($email) {
    $stmt = $this->pdo->prepare('SELECT COUNT(1) FROM users WHERE email = :email');
    $stmt->bindParam(':email', $email);
    $stmt->execute();
    $email_count = $stmt->fetchColumn();

    // and so on

最后,对于仅限 PHP 的文件,省略结束 PHP 标记 ?&gt;。这将避免您在可能发送到浏览器的文件末尾意外包含空格。

【讨论】:

  • 谢谢,关于数据库类,我的数据库连接是否应该在构造的单独函数中?基本上和上面一样,但不是在构造中?
【解决方案3】:

对于来这里寻求字面答案的人。

Use bindColumn

PDOStatement::bindColumn — 将列绑定到 PHP 变量

使用同一来源的示例:

function readData($dbh) {
  $sql = 'SELECT name, colour, calories FROM fruit';
  try {
    $stmt = $dbh->prepare($sql);
    $stmt->execute();

    /* Bind by column number */
    $stmt->bindColumn(1, $name);
    $stmt->bindColumn(2, $colour);

    /* Bind by column name */
    $stmt->bindColumn('calories', $cals);

    while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
      $data = $name . "\t" . $colour . "\t" . $cals . "\n";
      print $data;
    }
  }
  catch (PDOException $e) {
    print $e->getMessage();
  }
}
readData($dbh);

【讨论】:

    【解决方案4】:

    这是我的自定义函数:

    function bindColumns($stmt, $columns){
        if(!is_array($columns)) $columns=array($columns);
        $count=count($columns);
        for($i=0;$i<$count;$i++) $stmt->bindColumn($i+1, $columns[$i]);
    }
    

    及用法(变量引用):

    bindColumns($stmt, array(&$worker_id, &$password, &$salt));
    

    【讨论】:

      猜你喜欢
      • 2015-06-13
      • 2014-10-09
      • 2021-01-31
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 2014-05-08
      • 2014-06-12
      • 1970-01-01
      相关资源
      最近更新 更多