【问题标题】:changed object after storage or object-state used存储或使用对象状态后更改的对象
【发布时间】:2009-10-16 19:50:31
【问题描述】:

例子:

class UserStorage {
    public function addUser(User $user) { //saves to db }
}

class User {
    public function setName($name);
}

如果我将一个用户添加到用户存储并稍后更改该用户对象怎么办?在这种情况下,您可能会争辩说,用户对象应该只存储在 __destruct 上。但有时这不是一个选项(例如,想象用户在之后显示和更新)。

【问题讨论】:

    标签: php oop object state


    【解决方案1】:

    我同意 Peter 的观点,上述模型对我来说似乎有点古怪,我建议不要将隐式保存到数据存储区。

    此外,要使用的模式类似于:

    class UserStorage {
       $_user;
    
       function addUser(User user, commit = true) {
          if (commit) {
            // save to db
          } else {
            // populate your internal instance
            $_user = user;
          }
       }
    }
    

    因此,如果您在执行 PHP 应用程序时对 User 对象进行了多次更新,则可以使用

    addUser(user,false) 
    

    一直到最后一次调用

    addUser(user)
    

    这将减少对数据库进行多次插入/更新的需要。

    但是,您在应用程序中决定最终保存到数据库的位置的问题仍然存在,并且更多的是关于逻辑流而不是对象表示。在脚本中使用 end() 函数将所有对象持久保存到数据库中可能会有所帮助。

    【讨论】:

    • 我实际上不明白为什么它是隐含的。客户端代码创建一个用户对象并将其添加到用户存储中。
    • 这是隐含的,即存储对象没有被使用它的其他对象显式保存,即如果您选择在 __destruct 方法中保存到 db。如果您继续在代码中使用 addUser(),它是明确的,无需担心。
    【解决方案2】:

    隐式写入数据库可能是个坏主意。这应该是一个明确的、受控的操作。

    你的模式对我来说有点奇怪,但我认为这是你想要的方式

    class UserStorage
    {
        const ACTION_INSERT = 'INSERT';
        const ACTION_UPDATE = 'UDPATE';
    
        public function addUser(User $user)
        {
            $this->saveUser($user, self::ACTION_INSERT);
        }
    
        public function updateUser(User $user)
        {
            $this->saveUser($user, self::ACTION_UPDATE);
        }
    
        protected function saveUser(User $user, $action)
        {
            switch ($action) {
                case self::ACTION_INSERT:
                    //  INSERT query
                    break;
                case self::ACTION_UPDATE:
                    //  UPDATE query
                    break;
                default:
                    throw new Exception('Unsupported action');
            }
        }
    }
    
    class User
    {
        public function setName($name)
        {
            // whatever
        }
    }
    
    $userStorage = new UserStorage();
    $user = new User();
    
    $userStorage->addUser($user);
    
    $user->setName('Peter');
    
    try {
        $userStorage->updateUser($user);
    } catch (Exception $e) {
        echo "There was an error saving this user: " . $e->getMessage();
    }
    

    但就我个人而言,我并不热衷于此类设计。有一些成熟的模式不那么令人困惑,例如ActiveRecord

    【讨论】:

    • 我不是活跃唱片的忠实粉丝。但它可能有这样的优势 $object->save() 清楚地保存特定时刻的状态(即客户端代码知道它用它做了什么)。虽然也可能有一个缺点,当有多个代码使用 $object 时,不清楚谁负责触发 save()。
    • ActiveRecord 不是唯一的模式。例如,ZF 使用(表/行)数据网关。
    • 我认为它有同样的问题。该模型将隐藏网关。
    猜你喜欢
    • 1970-01-01
    • 2017-05-14
    • 2020-10-22
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 2020-06-21
    • 2020-12-08
    相关资源
    最近更新 更多