在使用__call方法加载它们后,如何检查类中存在哪些属性?

时间:2019-05-16 08:55:38

标签: php pdo

PDO具有预定义的提取模式,可以将其传递到fetchfetchAll方法中。我主要集中在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查询加载的什么属性,以获取必要的值。

例如,之前,我将emailuser_idusername列加载到该类中。我想更新该用户的密码。第一次提取中不存在此属性。如何检查类中存在哪些属性?

// 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));

0 个答案:

没有答案