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

kendrick's avatar

ProductController getProduct() Method (Query) Problem

Hey, Currently working on the correct routing for products, but facing some problems with the Controller as through ´->get()->first();´ only the first Product of every business will be shown following this route:

href="/products/{{ $product->business_id }}/{{ $product->id }}"

Eloquent: Business hasMany Product

Products Table: 'id, business_id'

ProductController.php

public function getProduct($product){
        $product = Product::where('id', $product)->get()->first();

        if(!$product){
            abort(404);
        }
        return view('products.index', compact('product'));
}

Route:

Route::get('/products/{business_id}/{id}', [
    'uses' => '\App\Http\Controllers\ProductController@getProduct', 
    'as' => 'products.index',
    'middleware' => ['auth:partner'],
    ]);

Any suggestions for a query or should I try $slug for this process? Thank you

0 likes
4 replies
martinbean's avatar

@splendidkeen Suggestion would be to use resourceful controller names and route–model binding. So your ProductController should have a show() method, and could have a Product instance injected:

class ProductController extends Controller
{
    public function show(Product $product)
    {
        return view('product.show', compact('product'));
    }
}

I’m not sure why you’re querying a product by ID, running get() and then first() in that single-result collection. If you need to query a product by ID then use Eloquent’s find() method (or even better findOrFail() which will throw an exception if a row with that ID does not exist):

$product = Product::findOrFail($id);

Other than that, I don’t really understand your problem.

only the first Product of every business will be shown

If your route contains the business ID and the product ID, then surely you only want a single product returned?

kendrick's avatar

Thank you for your reply @martinbean

This one works for the ProductController.php:

public function getProduct($id){
    
        $product = Product::findOrFail($id);

        if(!$product){
            abort(404);
        }
        return view('products.index', compact('product'));
}

But I am still facing the same problem. This is the process: As an authenticated Business, I can create as many products as I want, which will be stored in the Products table (id, business_id)

I created a dynamic product view, in which I parse in the content from the products. To get to the product view, I used the link:

 /products/{$product->business_id}/{$product->id}

But the view will only parse in the content from the first created product of the business, even though I clicked on the second product.

What is my mistake?

NowAndHere's avatar

Is your business id = 1? If you have more than one route parameters they are available in closure or controller in order of their appearance - in your route you have TWO parameters but in the controller only ONE. I would guess $id in your controller method will be business id not the product, you need to accept both parameters in your controller method:

(and start using route model binding, it will make your life easier)

use App\Business;
use App\Product'

public function show(Business $business, Product $product) {

    // You don't have to query database for business or
    // product as thanks to route model binding
    // Laravel has already done it for you
    // Just return your view:

    return view('products.show', compact(['business', 'product']);
}

BTW - just noticed you have products.index in your code. According to REST rules index is for listing all instances of the resource, you want to show details of specific resource, so use show for controller method and view name (don't make life of yourself and people that are to read your code difficult)

Snapey's avatar
Snapey
Best Answer
Level 122

You have to get all the products for business and then loop over them creating a URL for each product

BusinessController

public function show(Business $business)
{
    Business::load('products');

    return view ('business.index')->withBusiness($business);

}

business/index.blade.php

<h1> products of {{ $business->name }}</h1>

<ul>
@foreach($business->products as $product)

    <li><a href="{{ route('product.show', $product }}">{{ $product->name }}</a></li>

@endforeach
</ul>

ProductController

public function show(Product $product)
{
    
        return view('product.show', compact('product'));
}

Web.php

Route::get('/business/{business}','BusinessController@show')->name('business.show');

Route::get('/product/{product}','ProductController@show')->name('product.show');


but really the above is all guess work because we don't really know what your data looks like or what you want to do

Please or to participate in this conversation.