Abishek
Abishek

Reputation: 11691

How to increment a column using Eloquent Model in Laravel 4

I am not sure how to increment the value in a column using Eloquent Model in Laravel 4? This is what I currently have and I am not sure how correct is this.

$visitor = Visitor::where('token','=','sometoken')->first();
if(isset($visitor)){
    $visitor->increment('totalvisits');
}else{
    Visitor::create(array(
    'token'=>'sometoken',
    'totalvisits'=>0
    ));
}

With Query Builder we could do it using

DB::table('visitors')->increment('totalvisits');

Upvotes: 4

Views: 33343

Answers (3)

malhal
malhal

Reputation: 30573

Laravel 5 now has atomic increment:

public function increment($column, $amount = 1, array $extra = [])
{
    if (! is_numeric($amount)) {
        throw new InvalidArgumentException('Non-numeric value passed to increment method.');
    }
    $wrapped = $this->grammar->wrap($column);
    $columns = array_merge([$column => $this->raw("$wrapped + $amount")], $extra);
    return $this->update($columns);
}

which essentially works like:

Customer::query()
->where('id', $customer_id)
->update([
'loyalty_points' => DB::raw('loyalty_points + 1')
]);

Below is old answer for Laravel 4 where the built-in increment was a seperate select and then update which of course leads to bugs with multiple users:

If you'd like to accurately count your visitors by ensuring the update is atomic then try putting this in your Visitor model:

public function incrementTotalVisits(){
    // increment regardless of the current value in this model.
    $this->where('id', $this->id)->update(['totalVisits' => DB::raw('last_insert_id(totalVisits + 1)')]);

    //update this model incase we would like to use it.
    $this->totalVisits = DB::getPdo()->lastInsertId();

    //remove from dirty list to prevent any saves overwriting the newer database value.
    $this->syncOriginalAttribute('totalVisits');

    //return it because why not
    return $this->totalVisits;
}

I'm using it for a change tag system but might work for your needs too.

Does anyone know what to replace the "$this->where('id',$this->id)" with because since dealing with $this Visitor it should be redundant.

Upvotes: 2

Abishek
Abishek

Reputation: 11691

Looks like the code that I posted worked after all

$visitor = Visitor::where('token','=','sometoken')->first();
if(isset($visitor)){
    $visitor->increment('totalvisits');
}else{
    Visitor::create(array(
    'token'=>'sometoken',
    'totalvisits'=>0
    ));
}

Upvotes: 25

Jason Lewis
Jason Lewis

Reputation: 18665

Prior to a fix a few weeks ago the increment method actually fell through to the query builder and would be called on the entire table, which was undesirable.

Now calling increment or decrement on a model instance will perform the operation only on that model instance.

Upvotes: 5

Related Questions