Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

redlik's avatar

Bulk edit of products on front-end

I'll be building a small shop for a client and not sure how to tackle this task - bulk edits. Right now they are using OpenCart and I've install them an Excel import/export plugin where they export whole store, update prices / stock levels and import back into Opencart. In their new shop I would like to create a view where all products (or filtered list) has editable fields (price and qty) and allows for bulk edits, meaning change of data in one big list of items, without going into each one, change, save and go back. Not sure is that doable with pure laravel/blade/form or some JS magic involved.

0 likes
3 replies
rodrigo.pedra's avatar
Level 56

Wrap your table within a single <form>, and use array syntax on the inputs' names.

Proof of concept:

<?php

// ./routes/web.php

use App\Models\Product;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Route;
use Illuminate\Validation\Rule;

Route::get('/products', function () {
    $products = Product::all();

    return view('products.edit', ['products' => $products]);
});

Route::put('/products', function () {
    $validated = request()->validate([
        'products.*.id' => ['required', Rule::exists('products', 'id')],
        'products.*.price' => ['required', 'numeric', 'min:0'],
        'products.*.quantity' => ['required', 'integer', 'min:0'],
    ]);

    $input = Collection::make($validated['products']);

    Product::query()->whereKey($input->pluck('id'))
        ->each(function (Product $product) use ($input) {
            $record = $input->firstWhere('id', $product->getKey()) ?? [];

            $product->price = $record['price'] ?? 0;
            $product->quantity = $record['quantity'] ?? 0;

            $product->save();
        });

    return back()->with('success', 'updated!');
});

View ( ./resources/views/products/edit.blade.php:

<form action="{{ url('/products') }}" method="POST">
    @csrf
    @method('PUT')

    @if($message = session()->pull('success'))
        <p>{{ $message }}</p>
    @endif

    <table>
        <thead>
            <tr>
                <th>#</th>
                <th>Name</th>
                <th>Price</th>
                <th>Quantity</th>
            </tr>
        </thead>

        <tbody>
            @foreach($products as $product)
                <tr>
                    <th scope="row">
                        {{ $product->getKey() }}

                        <input type="hidden"
                               name="products[{{ $product->getKey() }}][id]"
                               value="{{ $product->getKey() }}">
                    </th>

                    <td>{{ $product->name }}</td>

                    <td>
                        <input type="text"
                               name="products[{{ $product->getKey() }}][price]"
                               value="{{ old("products.{$product->getKey()}.price", $product->price) }}">

                        @error("products.{$product->getKey()}.price")
                            <p>{{ $message }}</p>
                        @enderror
                    </td>

                    <td>
                        <input type="text"
                               name="products[{{ $product->getKey() }}][quantity]"
                               value="{{ old("products.{$product->getKey()}.quantity", $product->quantity) }}">

                        @error("products.{$product->getKey()}.quantity")
                            <p>{{ $message }}</p>
                        @enderror
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>

    <hr>

    <button type="submit">
        Save
    </button>
</form>

As a proof of concept I wasn't worried with styling, etc.

Hope it helps.

2 likes
redlik's avatar

Good man! I didn't expect a full ready to go code so fair play to you!

1 like

Please or to participate in this conversation.