Tip for Using incrementEach in Laravel

Laravel provides a convenient way to increment or decrement column values in a model using the increment and decrement methods. Starting from Laravel 9, an additional method, incrementEach (and decrementEach), allows updating multiple columns at once. The Problem: Incrementing and Decrementing Simultaneously What if you need to increment and decrement different columns at the same time? Consider the following scenario with a PriceImport model that has the columns imported_rows and unknown_rows. You might try something like this: PriceImport::query()->increment('unknown_rows')->decrement('imported_rows'); But, this approach won't work since increment and decrement methods can't be chained. Common Workaround (But Not Ideal) Typical way to handle this is by using DB::raw(): PriceImport::query()->whereKey($priceImport->id)->update([ 'imported_rows' => DB::raw('imported_rows + 1'), 'unknown_rows' => DB::raw('unknown_rows - 1'), ]); Or little better: PriceImport::query()->whereKey($priceImport->id)->increment('imported_rows', [ 'unknown_rows' => DB::raw('unknown_rows - 1'), ]); While this works, it's not the most elegant or laravel-friendly solution. The Elegant Solution: Using Negative Values with incrementEach Laravel’s incrementEach method allows passing negative values, which effectively works as a decrement operation. Here’s how you can achieve both incrementing and decrementing at the same time in a clean way: Full Example

Feb 28, 2025 - 17:04
 0
Tip for Using incrementEach in Laravel

Laravel provides a convenient way to increment or decrement column values in a model using the increment and decrement methods.

Starting from Laravel 9, an additional method, incrementEach (and decrementEach), allows updating multiple columns at once.

The Problem: Incrementing and Decrementing Simultaneously

What if you need to increment and decrement different columns at the same time?

Consider the following scenario with a PriceImport model that has the columns imported_rows and unknown_rows. You might try something like this:

PriceImport::query()->increment('unknown_rows')->decrement('imported_rows');

But, this approach won't work since increment and decrement methods can't be chained.

Common Workaround (But Not Ideal)

Typical way to handle this is by using DB::raw():

PriceImport::query()->whereKey($priceImport->id)->update([
    'imported_rows' => DB::raw('imported_rows + 1'),
    'unknown_rows' => DB::raw('unknown_rows - 1'),
]);

Or little better:

PriceImport::query()->whereKey($priceImport->id)->increment('imported_rows', [
    'unknown_rows' => DB::raw('unknown_rows - 1'),
]);

While this works, it's not the most elegant or laravel-friendly solution.

The Elegant Solution: Using Negative Values with incrementEach

Laravel’s incrementEach method allows passing negative values, which effectively works as a decrement operation.

Here’s how you can achieve both incrementing and decrementing at the same time in a clean way:

Full Example



namespace App\Actions\PriceImport;

use App\Actions\Actionable;
use App\Models\PriceImport\PriceImport;
use App\Models\PriceImport\PriceImportProduct;
use App\QueryBuilder\Queries\PriceImport\MovePriceImportDuplicateRowQuery;

final class PriceImportHandleDuplicateAction implements Actionable
{
    public function handle(PriceImport $priceImport): void
    {
        $duplicateCount = PriceImportProduct::query()
            ->where('row_occurrences', '>', 1)
            ->where('price_import_id', $priceImport->id)
            ->count();

        PriceImport::query()->whereKey($priceImport->id)->incrementEach([
            'imported_rows' => -$duplicateCount, // Decrementing
            'unknown_rows' => $duplicateCount,   // Incrementing
        ]);

        (new MovePriceImportDuplicateRowQuery($priceImport->id))->query();
    }
}

Resulting Query

UPDATE `price_imports`
SET `imported_rows` = `imported_rows` + -1,
    `unknown_rows` = `unknown_rows` + 1
WHERE `price_imports`.`id` = 5;

Conclusion

With this simple trick, you can increment and decrement multiple columns simultaneously using Laravel’s incrementEach method, making your code cleaner and more readable.