PDO具有预定义的提取模式,可以将其传递到fetch
和fetchAll
方法中。我主要集中在FETCH_CLASS
这个问题上。
为了将属性和值加载到类中,我创建了一个特征以允许使用魔术方法__set
。
trait Entity {
public function __construct() {
$this->_attributes = func_get_args();
}
public function __set($prop, $value) {
if (in_array($prop, $this->_attributes))
$this->$prop = $value;
}
}
然后使用类中的trait可以轻松地在整个应用程序中使用它。
class UserModel {
use Entity;
public function save() {
}
}
我现在遇到的问题是实现魔术方法__get
,现在可以根据类的属性和值保存数据。为了将数据加载到UserModel
中,我可以像这样创建一个PDO实例并进行查询:
$pdo = new PDO();
$stmt = $pdo->prepare('SELECT user_id, email, username, hash FROM app_users WHERE user_id = 1');
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_CLASS, 'UserModel');
我试图用特质生成其他__get
方法,如下所示:
public function __get($prop) {
if(isset($this->$prop)) return $this->$prop;
}
但是,我现在对PDO实例超出其范围时如何使用该实例来更新行感到困惑。我试图像这样为PDO实现单例特征:
trait Singleton
{
private static $instance;
public static function getInstance()
{
if(self::$instance) return self::$instance;
self::$instance = new self();
return self::$instance;
}
protected function __construct() {}
private function __clone() {}
}
PDO的一个非常快速的扩展,现在可以用于基本实现。
class PDOWrapper extends PDO
{
use Singleton;
protected function __construct()
{
parent::_construct('mysql:host=127.0.0.1;dbname=test;charset=utf8mb4', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
));
}
public function query($sql)
{
return parent::prepare($sql);
}
}
然后将更改将行提取到类中的整个方法,如下所示:
$stmt = PDOWrapper::getInstance()->query('SELECT user_id, email, username, hash FROM app_users WHERE user_id = 1');
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_CLASS, 'UserModel');
现在在我的save()
方法中,我可以使用PDOWrapper::getInstance()
访问相同的PDO实例。我遇到的问题是,您需要知道从SQL查询加载的什么属性,以获取必要的值。
例如,之前,我将email
,user_id
和username
列加载到该类中。我想更新该用户的密码。第一次提取中不存在此属性不。如何检查类中存在哪些属性?
// Won't work
public function save() {
$stmt = PDOWrapper::getInstance()->query('UPDATE app_users SET hash = ? WHERE user_id = ?');
$stmt->execute(array($this->__get('hash'), $this->__get('user_id')));
}
我需要一个针对属性集动态的解决方案,例如,可能应该全部是批处理更新:
// Sudo code
PDOWrapper::getInstance()->beginTransaction(); // Will need to be added
foreach($this->props as $prop)
PDOWrapper::getInstance()->query('UPDATE table SET prop = value where user_id = value')->execute(array($this->$prop, $this->user_id));