【问题标题】:[PHP / PDO CLASS]Fatal error: Call to a member function fetch() on boolean[PHP / PDO CLASS]致命错误:在布尔值上调用成员函数 fetch()
【发布时间】:2017-06-18 02:33:43
【问题描述】:

每当我尝试使用我的 PDO 数据库包装器从我的数据库中获取某些内容时都会收到此错误:
Fatal error: Call to a member function fetch() on boolean in C:\xampp\htdocs\index.php on line 17

index.php

require_once 'class.db.php';
$mysql = [
    'hostname'  => '127.0.0.1',
    'database'  => 'lucidcms',
    'username'  => 'root',
    'password'  => 'test',
    'charset'   => 'utf8',
];
$db = new Database($mysql);

$u = "Sentinel";

$result = $db->prepare("SELECT `id` FROM `users` WHERE `username` = :u LIMIT 1")
             ->execute([':u' => $u])
             ->fetch();
echo $result;

class.db.php

<?php
class Database {

    private static $stmt, $pdo;

    public function __construct(array $mysql) {
        if(is_null(self::$pdo)) {
            try {
                self::$pdo = new \PDO(
                    'mysql:dbname='.$mysql['database'].';host='.$mysql['hostname'].';charset='.$mysql['charset'], 
                    $mysql['username'], 
                    $mysql['password'],
                    [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, \PDO::ATTR_PERSISTENT => true]
                );
            } catch(PDOException $e) {
                die('An error occurred when trying to communicate with the database.');
                //die($e->getMessage());
            }
        } else {
            return new self;
        }
    }

    public function __destruct() {
        // Destruct the connection to DB once finished
        try {
            self::$pdo = null;
        } catch(PDOException $e) {
            die('An error occurred when trying to close the connection with the database.');
            //die($e->getMessage());
        }
    }

    public static function prepare($sql) {
        self::$stmt = self::$pdo->prepare($sql);
        return self::$stmt;
    }

    public static function execute($data = []) {
        return self::$stmt->execute(isset($data) ? $data : null);
    }

    public static function count() {
        return self::$stmt->rowCount();
    }

    public static function fetch() {
        return self::$stmt->fetchColumn();
    }

    public static function fetchAll($type = \PDO::FETCH_ASSOC) {
        return self::$stmt->fetch($type);
    }

    public static function lastId() {
        return self::$pdo->lastInsertId();
    }

}

我似乎真的不知道如何解决这个错误。
关于我做错了什么的任何想法?

编辑,新的工作解决方案,但编码相当混乱:

<?php
class DB {
    private static $host;
    private static $db;
    private static $dbuser;
    private static $pass;
    private static $char;

    private static $pdo, $stmt;  

    public function data($mysql) {
        self::$host   = $mysql['hostname'];
        self::$db     = $mysql['database'];
        self::$dbuser = $mysql['username'];
        self::$pass   = $mysql['password'];
        self::$char   = $mysql['charset'];
    }

    protected function __clone() {}

    public static function connect() {
        if(is_null(self::$pdo)) {
            try {
                self::$pdo = new \PDO(sprintf("mysql:host=%s;dbname=%s;", 
                    self::$host,
                    self::$db), 
                    self::$dbuser, 
                    self::$pass,
                    [
                        \PDO::ATTR_EMULATE_PREPARES => false, 
                        \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
                    ]
                );
            } catch(PDOException $e) {
                die('An error occurred when trying to communicate with the database.');
            }
        } else {
            return self::$pdo;
        }
    }

    public function __destruct() {
        // Destruct the connection to DB once finished
        try {
            self::$pdo  = null;
        } catch(PDOException $e) {
            die('An error occurred when trying to close the connection with the database.');
            //die($e->getMessage());
        }
    }

    public static function prepare($sql) {
        DB::connect();
        self::$stmt = self::$pdo->prepare($sql);
        return new self;
    }

    public static function execute($data = []) {
        DB::connect();
        try {
            self::$stmt->execute(isset($data) ? $data : null);
        } catch(PDOException $e) {
            die("Execution error: " . $e->getMessage());
        }
        return new self;
    }   

    public static function fetchAll($type = \PDO::FETCH_BOTH) {
        DB::connect();
        return self::$stmt->fetch($type);
    }

    public static function fetch() {
        DB::connect();
        return self::$stmt->fetchColumn();
    }

}

有什么方法可以将 connect() 和 data() 变成 __construct() 函数?

【问题讨论】:

  • 哦,让我看不到这个。

标签: php mysql class pdo


【解决方案1】:

你做错了很多事情,(完全改变了方法名称!)但是你得到的错误信息很清楚:如果你想使用方法链接,你应该像这样编写每个方法prepare iswritten() - 使其返回语句。

但是,由于它的statefulness,这个类无法挽救,因为它会导致生产中的严重错误。让我建议另一种解决方案,而不是这种麻烦的混乱,更轻量级且不易出错

class MyPDO extends PDO
{
    public function run($sql, $args = NULL)
    {
        $stmt = $this->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }
}

通过这个简单的扩展,您将能够在您的 SELECT 查询中使用方法链接,而不会弄乱您的代码。

$result = $db->run("SELECT `id` FROM `users` WHERE `username` = :u LIMIT 1", [':u' => $u])
             ->fetch();

它不像您当前的方法那么整洁,但同样 - 它没有可怕的缺点。

【讨论】:

  • 谢谢,我去看看。
  • 太糟糕了。
  • Ikr,但我不会真正使用,它只是用于测试目的。
猜你喜欢
  • 2016-05-18
  • 2019-04-19
  • 1970-01-01
  • 1970-01-01
  • 2015-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多