如何确定 class 中的哪些属性应包含在 UPDATE 动态查询中?

How to determine which properties from class should be included in an UPDATE dynamic query?

图 1:这是一个示例模型 class

class Games {
    public $id = 0;
    public $date = null;
    public $player1_id = 0;
    public $player2_id = 0;
    public $score = null;

    public function save(){
        if(empty($this->id)){
            // do INSERT here
        }
        else{
            // do UPDATE here  
        }
    }
}

图 2:这是 class

的使用示例
// Save a new date to an existing game
$game = new Games;
$game->id = $input['id'];
$game->date = $input['date'];
$game->save();

如果根据 图 2 执行 UPDATE 查询,则 player1_idplayer2_idscore 的值] 将被错误地覆盖为 zeros/nulls。因此,我需要一种方法从 class 内部确定某些属性未通过 figure2 中的调用设置 ,所以我可以动态更改 UPDATE 查询以仅更新数据库中的特定字段。还是我处理错了?

注意:我知道我可以使用单个 array 属性 来保存所有字段(并使用 isset),但这感觉像是打破了模型的要点并且也会非常 PHP 具体(因为解决方案不能很好地转移到其他语言,例如 JAVA 数组是严格类型化的?)。我还意识到我可以做我认为 ORM 所做的事情,并在执行更新之前进行初始 SELECT 查询(但这似乎非常低效!)

Select 您的对象,然后再更新它。这样,您的 UPDATE 语句将包含所有字段。

此外,这让您可以检查该 ID 是否存在。

否则,简单来说SQL你可以这样做:

UPDATE games SET date = "2015-01-26", anotherField = $game->anotherField() WHERE id = $game->id;

注意:这是伪代码。使用准备好的语句:http://php.net/manual/en/pdo.prepared-statements.php

反思文档:http://php.net/manual/en/book.reflection.php

  1. 声明一个 PRISTINE 常量。尝试将其设置为您创建的对象的新实例,例如 new MyPristine。
  2. 在您的游戏构造函数中,将所有字段设置为该常量。这是将它们标记为“未触及”的技巧。您可以使用反射(如 ReflectionClass($game)->getProperties() )循环遍历所有这些
  3. 保存之前,再次遍历字段并使用 PRISTINE 测试它们的值。如果不同,则需要更改。

此解决方案假设没有 one/nothing 否则会在步骤 2 和 3 之间更改 Game 实例。这就是为什么大多数 ORM 会预先执行 SELECT。