Laravel4 Model primary key value is lost after insert

孤人 提交于 2020-01-14 22:32:15


// Model
class ProfileDelivery extends \Eloquent {
    protected $table = 'profile_delivery';
    protected $guarded = array();
    public $timestamps = FALSE;

// Somewhere
$deliveryGuy->id = 1;
print $deliveryGuy->id; // Prints 1
if (!$deliveryGuy->save()) {
    throw new \Exception('Cant save .');
print $deliveryGuy->id; // Prints 0

Can anyone explain me why the ID value is lost?


Not sure if you solved this for your situation but in Laravel 5.1 this just happened to me - the primary key of one table is the same as the primary key to another table because there is a 0 or 1 - to - 1 relationship between them.

What is happening is that Eloquent is assigning the primary key to the last insert id of the insert, but because the primary key is not an auto increment value, it is assigning it to zero. It is stored in the database correctly, but the model after the save is not useful if you need to use that key. The solution is to override the insertAndSetId function for the model that has the foreign primary key to prevent its setting of the primary key attribute. Of course, you don't want to do this for any models that do have an auto-incrementing key, just models that you are assigning the primary key manually. It's also not necessary if you don't need to use the model immediately after creating it because as I said above the database has the correct info in it.

protected function insertAndSetId(Builder $query, $attributes)
    $id = $query->insertGetId($attributes, $keyName = $this->getKeyName());

    // $this->setAttribute($keyName, $id);


This is because your id column in the database probably does not have autoincrement set.

I tried this with a test model without autoincrement and it returns 0, but when I changed the id column to autoincrement it returned the id correctly.

Check this function in laravel/Framework/Src/Illuminate/Database/Eloquent/Model.php

It says it will insert and set id if it has autoincrement.

protected function performInsert($query)
        if ($this->fireModelEvent('creating') === false) return false;

        // First we'll need to create a fresh query instance and touch the creation and
        // update timestamps on this model, which are maintained by us for developer
        // convenience. After, we will just continue saving these model instances.
        if ($this->timestamps)

        // If the model has an incrementing key, we can use the "insertGetId" method on
        // the query builder, which will give us back the final inserted ID for this
        // table from the database. Not all tables have to be incrementing though.
        $attributes = $this->attributes;

        if ($this->incrementing)
            $this->insertAndSetId($query, $attributes);

        // If the table is not incrementing we'll simply insert this attributes as they
        // are, as this attributes arrays must contain an "id" column already placed
        // there by the developer as the manually determined key for these models.

        // We will go ahead and set the exists property to true, so that it is set when
        // the created event is fired, just in case the developer tries to update it
        // during the event. This will allow them to do so and run an update here.
        $this->exists = true;

        $this->fireModelEvent('created', false);

        return true;


For me, I had to set protect $primaryKey to the column name of the primary key in the model to solve the issue. (skill_id was the column name so in the Skill model I set protected $primaryKey = 'skill_id', default is 'id'.)