dri8163 2019-05-16 08:55
浏览 48

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

PDO has a predefined fetch modes that can be passed into the fetch and fetchAll methods. I am mainly concentrating on FETCH_CLASS in my issue.

In order to load the properties and values into my class I created a trait to allow for magic methods __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;
  }
}

This then can be easily used across the application by using the trait in a class.

class UserModel {
    use Entity;

    public function save() {

    }
}

The issue I am having now is implementing the magic method __get to now be able to save the data based off the class properties and values. In order to load data into the UserModel, I can just create a PDO instance and query like so:

$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');

I tried to generate the additional __get method in my trait like so:

public function __get($prop) {
    if(isset($this->$prop)) return $this->$prop;
}

But I am now stuck with how to use the instance to update the row when the PDO instance is outside of its scope. I tried to implement a singleton trait for the PDO like so:

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() {}
}

And a really quick extension of the PDO for basic implementation for now.

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

Which then changes my whole approach to fetching the row into the class to look something like this:

$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');

Now inside my save() method, I have access to the same PDO instance using PDOWrapper::getInstance(). The issue I have is that you need to know what properties where loaded from the SQL query to get the necessary values.

For example, prior, I loaded the email, user_id and username columns into the class. I want to update the password for that user. This property does not exist in the first fetch. How can I check what properties exist in the class?

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

I need a solution that is dynamic to the properties set, for example which should probably all be a batch update:

// 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条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥15 虚幻5 UE美术毛发渲染
    • ¥15 CVRP 图论 物流运输优化
    • ¥15 Tableau online 嵌入ppt失败
    • ¥100 支付宝网页转账系统不识别账号
    • ¥15 基于单片机的靶位控制系统
    • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
    • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
    • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
    • ¥15 手机接入宽带网线,如何释放宽带全部速度
    • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测