How to pass a value in a form action in laravel

I have a view that list all objects in a database and for each object creates a form for saving to a different table. My problem is, that the value isn't being passed to my function.

Here is my blade.php file:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">{{ __('Items') }}</div>
                <div class="card-body">
                    <div class="row">
                    @foreach($items as $item)
                        <div class="col-md-3 col-xs-12">
                            <div class="card">
                                <img src="..." class="card-img-top" alt="...">
                                <div class="card-body">
                                    <h5 class="card-title">{{ $item->name }}</h5>
                                    <p class="card-text">$ {{ $item->price }}</p>
                                    @auth
                                    <form method="post" action="{{ route('carts.store', $item) }}"> 
                                        @csrf
                                        @method('post')
                                        <button type="submit" class="form-control btn">add to cart</button>
                                    </form>
                                    @endauth

                                    <form method="post" action="{{ route('item.destroy', $item) }}"> 
                                        @csrf
                                        @method('delete')
                                        <button type="submit" class="form-control btn btn-danger">delete</button>
                                    </form>
                                </div>
                            </div>
                        </div>
                    @endforeach
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

and my function in the CartsController:

public function store(Item $item)
{
    $cart = new Cart();
    $cart->user_id = auth()->id();
    $cart->item_id = $item->id;
    
    $cart->save();

    return redirect('/item');
}

When I click on add to cart I get this error:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'item_id' cannot be null (SQL: insert into `carts` (`user_id`, `item_id`, `updated_at`, `created_at`) values (1, ?, 2020-08-24 07:35:44, 2020-08-24 07:35:44))

I've tried passing the id to the function directly but that also doesn't seem to work. I'm very confused as to why this is happening since I can use $item two rows earlier without a problem.

Upvotes: 3

Views: 2531

Answers (1)

Spholt
Spholt

Reputation: 4032

Provided that your route model binding is setup correctly, it won't actually matter whether you pass the id of an object or the object itself to the the route() function.

https://laravel.com/docs/7.x/routing#implicit-binding

When you run php artisan route:list, you should see something similar to this:

POST | cart/store/item/{item} | carts.store | App\Http\Controllers\CartController@store 

Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.

So any of the following will actually work

{{ route('carts.store', $item) }}

OR

{{ route('carts.store', $item->id) }}

OR

{{ route('carts.store', ['item' =>  $item->id]) }}

Should all resolve to the same thing.


Addendum

So the route you are using doesn't have a route parameter for your item (i.e {item}), as such it won't know which Item object you are referencing.

You can either:

  1. Amend your route to include this route parameter

OR

  1. use the Request object to resolve the Item instead.

Blade

<form method="post" action="{{ route('carts.store') }}"> 
    @csrf
    @method('post')
    <input type="hidden" name="item_id" value="{{ $item->id }}">
    <button type="submit" class="form-control btn">add to cart</button>
</form>

Controller

public function store(Request $request)
{
    $cart = new Cart();
    $cart->user_id = auth()->id();
    $cart->item_id = $request->item_id;
    
    $cart->save();

    return redirect('/item');
}

Upvotes: 2

Related Questions