Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Models incorrectly try to be replaced instead of update

I am trying to update the name of a user id=1. I tried the following code (v 1.3). But instead of updating, it t replaces the user and var_dump($n->getMessages()); outputs errors relating to not null attributes.

 class UserApi extends Phalcon\DI\Injectable{}

 $n=new User;
$n->id=1;
 $n->name='Tom';
 $n->save(); //or even $n->update()

User::findFirst(1)->save(); works. But I prefer to use a single code for both create and update operations.



84.5k

Every object in the ORM has 3 states:

  • DIRTY STATE PERSISTENT: The object is attached to a row persisted in the database
  • DIRTY STATE TRANSIENT: The object is created in the application userland by is not attached to a row persisted in the database
  • DIRTY STATE DETACHED: The object exists in the application and it was recently detached from a row persisted in the database

When you create an object it's in TRANSIENT state, you can only update objects when they're in PERSISTENT state. findFirst() and find() returns objects in PERSISTENT state which are capable of being updated to the persistance.



13.3k

Thanks. But I didn't get it. In documentation:

The save method is called internally by the create and update methods of Phalcon\Mvc\Model. For this to work as expected it is necessary to have properly defined a primary key in the entity to determine whether a record should be updated or created.

I want to create/update data rows with single code block. How can I do that?



84.5k
Accepted
answer
edited Jun '14

What the documentation says is that a record is checked (not retrieved) if it does exist in the persistance to trigger the proper events/hooks before save it.

You can do this:

$user = User::findFirst(1);
if (!$user) {
    $user = new User;
    $user->id = 1;   
}
$user->name = "Tom";
$user->save();

Or add a method like this to your model:

class User extends Phalcon\Mvc\Model
{
    public static function createOrGet($id)
    {
        $user = User::findFirst($id);
        if (!$user) {
            $user = new User;
            $user->id = $id;     
        }       
        return $user;   
    }
}

Usage:

$user = User::createOrGet(1);
$user->name = "Tom";
$user->save();


13.3k

Is there any resource to read more about ORM 3 states? The current implementaion does not seems natural for me.



13.3k
edited Feb '15

Larval has some similar methods:

  // Create a new user in the database...
  $user = User::create(['name' => 'John']);

  // Retrieve the user by the attributes, or create it if it doesn't exist...
  $user = User::firstOrCreate(['name' => 'John']);

  // Retrieve the user by the attributes, or instantiate a new instance...
  $user = User::firstOrNew(['name' => 'John']);