changed object after storage or object-state used

2019-09-02 09:05发布

问题:

Example:

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

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

What if I add a user to the user storage and later change that user object? In this case you might argue that user objects only should be stored on __destruct. But sometimes this isn't an option (eg imagine the user is displayed and updated afterwards).

回答1:

I agree with Peter, the above model seems a little quirky to me and I would recommend against implicit save to the datastore.

Additionally, a pattern to use is something like:

class UserStorage {
   $_user;

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

So if you have multiple updates of a User object in the execution of your PHP application, you can use

addUser(user,false) 

all the way until the very last call to

addUser(user)

This will alleviate the need for multiple inserts/updates to the DB.

However, your problem of where in the application to decide to finally save to db remains, and is more about logical flow than object representation. It may be helpful to have a end() function in the script that persists all your objects to the db.



回答2:

Implicit writes to the database are probably a bad idea. That should be an explicit, controlled operation.

Your pattern is a little weird to me, but I think this how you'd want to do it

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

But Personally I'm not crazy about this class design. There are some well-established patterns for this that are less confusing, such as ActiveRecord.