如何使用 PHP PDO 解析 MySQL 数据库中的对象数据?
Posted
技术标签:
【中文标题】如何使用 PHP PDO 解析 MySQL 数据库中的对象数据?【英文标题】:How do I parse object data from MySQL database using PHP PDO? 【发布时间】:2017-08-23 14:14:34 【问题描述】:我在尝试从数据库返回对象数据时遇到了问题。我跟着this tutorial 构建了一个数据库包装器,并一直在尝试扩展它的功能以满足我的需求。我的问题是,当我使用 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>';
【问题讨论】:
警告:编写自己的访问控制层并不容易,而且有很多机会会严重错误。当任何现代的development framework(如Laravel)带有强大的authentication system 内置时,请不要编写自己的身份验证系统。至少关注recommended security best practices。 该教程不是我见过的最糟糕的教程,但也不是很好,实际上仅从学术角度来看有用。我强烈建议您不要将此代码用于任何严重的事情,甚至是部署到公共互联网的任何事情。即使是最小的错误的风险也非常高,因此使用受信任的、经过社区审查的代码是一个更好的主意。 谢谢@tadman。我知道这不是最好的方法,但在开始使用框架之前,我真的很想了解这一点,所以我可能对框架的工作原理有更好的了解。 我认为这是一个相当不错的速成课程,例如,他们涉及 CSRF,这令人鼓舞,但您需要找到一个适合您的风格和需求的更严肃工作的生产质量框架.有很多可供选择。这个特定教程的问题是他们没有正确地散列密码,这可能是一个严重的问题。 【参考方案1】:这些视频教程的问题在于他们的作者对这个主题一无所知,这使得结果比你根本不使用他们的精神排泄物要糟糕得多。他们造成的破坏是如此严重,以至于我什至不得不写一篇专门的文章来解释为什么所有这些无助的“包装器”对于任何现实生活中的应用程序都完全无法使用,Your first database wrapper's childhood diseases。
以视频中的这个包装器为例:
错误报告完全有缺陷 SELECT 的无用函数。 有状态 受保护的 PDO 实例因此,从本质上讲,您将无法从这个“包装器”中获得即使是插入 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 已经可以为您提供对象数据,而无需额外的一行代码。
虽然这个简单的例子不是很令人印象深刻,但这里的秘密是这个包装器也可以为您提供任何其他示例,当来自视频的内容会窒息时。尝试考虑任何其他示例,我将向您展示这个包装器是多么简单而强大。
【讨论】:
以上是关于如何使用 PHP PDO 解析 MySQL 数据库中的对象数据?的主要内容,如果未能解决你的问题,请参考以下文章