如何使用PHP PDO解析MySQL数据库中的对象数据?

时间:2017-03-29 21:35:20

标签: php mysql oop pdo

我在尝试从数据库返回对象数据时遇到了问题。我跟着this tutorial构建了一个DB包装器,并一直在尝试扩展它的功能以满足我的需求。我的问题是,当我使用DB类“get”方法返回数据时,它还返回PDO对象本身的实例。我想知道我如何解析这些数据,以便我只返回数据库中的对象,而不是数据库对象本身。我希望最终能够为每个对象显示不同的数据库值。

以下是我的所有相关代码:

class DB {

private static $_instance = null; //stores instance of database
private $_pdo, 
        $_query, 
        $_error = false, 
        $_results, 
        $_count = 0;


private function __construct() {
    try {
        $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/db'), Config::get('mysql/username'),  Config::get('mysql/password'));
    } catch(PDOException $e){
        die($e->getMessage());
    }
}


public static function getInstance() {
    if(!isset(self::$_instance)){
        self::$_instance = new DB();
    }
    return self::$_instance;
}

public function query($sql, $params = array()){
    $this->_error = false;
    if($this->_query = $this->_pdo->prepare($sql)) {
        $x = 1;
        if(count($params)) {
            foreach($params as $param) {
                $this->_query->bindValue($x, $param);
                $x++;
            }
        }
        if($this->_query->execute()) {
            $this->_results = $this->_query->fetchAll(PDO::FETCH_OBJ);
            $this->_count = $this->_query->rowCount();
        } else {
            $this->_error = true;
        }
    }
    return $this; 
}


public function action($action, $table, $where = array()) {
    if(count($where) === 3) {
        $operators = array('=', '>', '<', '>=', '<=');

        $field = $where[0];
        $operator = $where[1];
        $value = $where[2];

        if(in_array($operator, $operators)) {
            $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
            if(!$this->query($sql, array($value))->error()) {
                return $this;
            }
        }

    } return $this;

}

public function get($table, $where) {
    return $this->action('SELECT *', $table, $where);

}
}

class Schedule {

private $_db;
protected $_games = array();

public function __construct() {

    $this->_db = DB::getInstance();

}

public function listGames() {

    $data = $this->_db->get('games', array('id', '>', 0));
    var_dump($data);

    echo '<br>';

}
}

1 个答案:

答案 0 :(得分:5)

这些视频教程的问题在于他们的作者对这个问题没有任何线索,结果比你根本没有使用他们的精神粪便要好得多。他们造成的伤害是如此糟糕,以至于我甚至不得不写一篇专门的文章来解释为什么所有这些无助的“包装”完全无法用于任何现实生活应用,Your first database wrapper's childhood diseases

从视频中获取此包装器,例如:

  • 错误报告完全有缺陷
  • SELECT的无用功能。
  • 有状态
  • 受保护的PDO实例

所以,从本质上讲,你甚至无法从这个“包装器”中获得像Insert Id那样愚蠢的东西。并且没有任何错误报告可以帮助您实现问题。

从您的代码开始,只是不要为了节省自己输入SQL关键字而讨价还价。这太傻了。 SQL是一件珍贵的事情,不要因为一些胡言乱语而忽略它。你也不应该将PDO缩小到残缺无效的状态,摒弃其最辉煌的特征。

您的包装器应该可以访问所有PDO和SQL功能,而不是丢弃它们。所以它是:

class DB
{
    protected static $instance;
    protected $pdo;

    protected function __construct() {
            $opt  = array(
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
                PDO::ATTR_EMULATE_PREPARES   => FALSE,
            );
            $dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset='.DB_CHAR;
            $this->pdo = new PDO($dsn, DB_USER, DB_PASS, $opt);

    }

    // a classical static method to make it universally available
    public static function instance()
    {
        if (self::$instance === null)
        {
            self::$instance = new self;
        }
        return self::$instance;
    }

    // a proxy to native PDO methods
    public function __call($method, $args)
    {
        return call_user_func_array(array($this->pdo, $method), $args);
    }

    // a helper function to run prepared statements smoothly
    public function run($sql, $args = [])
    {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }
}

这个包装器比视频的十倍更简单,同时也是十倍。

现在你的班级

class Schedule
{
    private $_db;

    public function __construct()
    {
        $this->_db = DB::instance();
    }

    public function listGames()
    {
        $data = $this->_db->query('SELECT * FROM games')->fetchAll();
        var_dump($data);
        echo '<br>';
    }
}

这里的秘密是PDO已经可以为您提供对象数据,而不需要额外的一行编码。

虽然这个简单的例子不是很令人印象深刻,但这里的秘诀在于,当视频中的内容会窒息时,这个包装器将为您提供任何其他示例。试着想一下其他任何一个例子,我会告诉你这个包装器有多么简单但功能强大。