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

JoaoHamerski's avatar

How to use policies in this case?

So, i have two models, Client and Product, a Client can have many Products, and a Product belongs to a Client, in the URL i have http://localhost:8000/clients/15/products/153, my issue is when i change the product id in the URL, Laravel returns to me the client with id = 15, but a Product from another client that is not the 15. For example: http://localhost:8000/clients/15/products/1, it returns to me the product 1 and client 15, but the client 15 doesnt have any product with id of 1, so, in my controller i did:

  
if ($client->id != $product->client->id) {
    \App::abort(403);
}

And works fine, but i would like to do it with Policies or something like that, a better way, how can i do it?

I created a ProductPolicy and in the view method i did:

public function view(Client $client, Product $product)
{
    return $client->id === $product->client->id;
}

But when i use $this->authorize('view', [$client, $product]); on my ProductController, this give me error 403 forbidden all the time, even if the $product->client->id and $client->id matches.

Someone else knows the correct way to do it? What am i doing wrong?

0 likes
30 replies
Sinnbeck's avatar

Try using dd on the line before return to check what comes in. My best bet is that it does not hit the policy

public function view(Client $client, Product $product)
{
    dd($client, $product);
    return $client->id === $product->client->id;
}
JoaoHamerski's avatar

Yes, it's not hitting the policy method, but why? I don't understand.

JoaoHamerski's avatar

It gives me 403 Fobidden all the time, doesn't even hit the view method.

Sinnbeck's avatar

Just noticed the problem. You have a product policy but you pass in client first

$this->authorize('view', [$product, $client]);

And 

public function view(Product $product, Client $client)
{
    return $client->id === $product->client->id;
}
JoaoHamerski's avatar

It just doesn't hit the method yet.

This is my AuthServiceProvider:

class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
    Product::class => ProductPolicy::class,
];


public function boot()
{
    $this->registerPolicies();

    //
}

}

My ProductPolicy:

/**
 * Determine whether the user can view the product.
 *
 * @param  \App\User  $user
 * @param  \App\Product  $product
 * @return mixed
 */
public function view(Product $product, Client $client)
{
    dd('asd');
    return $client->id === $product->client->id;
}

My ProductsController

public function show(Client $client, Product $product)
{   
    $this->authorize('view', [$product, $client]);

    if ($client->id != $product->client->id) {
        // \App::abort(403);
    }        

    return view('products.show', compact(['client', 'product']));
}
JoaoHamerski's avatar

It returns 403 forbidden in any URL like =

http://localhost:8000/clients/X/products/Y

Sinnbeck's avatar

Strange indeed. Can you try the middleware instead? Use on the route

Route::get ('someurl', 'Controller@view')->middleware('can:view, App/Product');
JoaoHamerski's avatar

It gives me the same result, doesn't hit the view method in my PolicyProduct

Sinnbeck's avatar

Do you have a before method in the policy?

JoaoHamerski's avatar

No, i don't, only the view method in my ProductPolicy

Sinnbeck's avatar

Try adding a new method with only the product and then only pass the product. Does it hit that?

JoaoHamerski's avatar

It doesnt hit the method as well:

ProductPolicy:

    public function newMethod(Product $product)
    {
        dd('aaa');
    }

ProductsController

public function show(Client $client, Product $product)
    {   
        $this->authorize('newMethod', $product);
    if ($client->id != $product->client->id) {
        // \App::abort(403);
    }        

    return view('products.show', compact(['client', 'product']));
}
Sinnbeck's avatar

Did you remember to remove the middleware again before testing?

JoaoHamerski's avatar

Yes, i did, i tried with the middleware and without the middleware.

JoaoHamerski's avatar

wow i really don't know what is happening, i searched on forums and many people have the same problem, or maybe it's something to do with Windows? I really don't know, so weird why they never fixed it.

Sinnbeck's avatar

Sadly I am running Linux and it works perfectly.

Perhaps try clearing caches (even though I doubt it is that)

php artisan optimize:clear 
composer dump-autoload
JoaoHamerski's avatar

Yea, it simply doesnt hit the method in ProductPolicy, but thanks for the help anyway, if i find a solution i will reply this thread to help someone else.

Sinnbeck's avatar

Yeah I have had issues with that but the reason was mismatch of classes. I don't suppose you have more than one Product model?

JoaoHamerski's avatar

No, i have 5 models: Client, Component, Payment, Product and User and 3 controllers for: Clients, Components and Products.

Sinnbeck's avatar

My last suggestion is to put the project on github (or zip it) so I can test it myself

JoaoHamerski's avatar

You can run "php artisan migrate -seed" and go to some product.show like localhost:8000/clientes/1/produtos/1 (sorry, the routes are in portuguese brazilian).

Sinnbeck's avatar

I am not at a computer right now. I will clone it tomorrow and give it a try

Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

How do I login? To work you need to be logged in. If that is not possible you need to set the User parameter as optional

https://laravel.com/docs/6.x/authorization#guest-users

public function view(?User $user, Product $product)
    {
        dd('asd');
    }

And in controller change $client to $product

$this->authorize('view', $product);

This works.

Sinnbeck's avatar

@joaohamerski Hope you got it working. It at least works for me with a few tweaks, meaning you can get it working to :)

JoaoHamerski's avatar

@sinnbeck Woow, it works perfectly thank you sooo much, i found many threads in forums with the same problem, maybe this solution should be added in the documentation, people didn't notice that yet.

JoaoHamerski's avatar

Thanks, i did not noticed that, because as you could see my site there is no user yet, so i totally ignored this part, my bad.

Sinnbeck's avatar

No worries. Just happy you got it working.

1 like

Please or to participate in this conversation.