Scoping component data based on url path

I’ve setup company-scoped routes, such as

Each user may have access to multiple companies, so the path determines the scope, making sure that I will only load products for company A when visiting the first url.

I have set up n auth helper auth()->company() which will simply return the current company, based on the path, so I can do things like: auth()->company()->products()

// return the current company via auth()->company() or Auth::company()
SessionGuard::macro('company', function () {
  return $this->request->company;
});

I tried setting up a Livewire component for the products list, but noticed that it only works on the inital page load. On ajax calls, the scope is gone, because the url that livewire calls (myapp.com/livewire/message/products-list) does not contain the company slug anymore, meaning that I will get an error like

Call to a member function products() on null

I tried passing the company as a param to the products-list component:

<livewire:products-list :company="auth()->company()">

and in the component, using it:

public function render()
{
    return view('livewire.products-list', [
        'products' => $this->company->products()
            ->orderBy('name')
            ->paginate()
    ]);
}

but again, this only works on the inital pageload.

Essentially, I would need to either customize the livewire url, so it’s prefixed with the company slug, or find another way to pass the current company scope to livewire. I’d prefer if I could just call auth()->company() though.

Any ideas?

There’s a couple of way I can see to do this, and I think the easiest way is going to be to persist the company id in the mount method, and use that for your calls.

<livewire:products-list :companyID="auth()->company()->id">

public function render()
{
    return view('livewire.products-list', [
        'products' => Company::find($this->companyID)
            ->products()
            ->orderBy('name')
            ->paginate()
    ]);
}

Couldn’t this be something that can be easily tampered with, though? The company ID is sent in the AJAX request back to the server, and the request could be intercepted and the company ID could be swapped, right?

So another layer of security would be needed server-side, to authorize whjether teh current user can even access the given company.

Just for clarity - this is a multi-tenant platform, where we have users and companies with many-to-many relationships.

Not easily, no. The checksum would fail and you would get a corrupted data (or similar, I forget the wording) exception thrown.

But I do get your concern, so another good way is to use a protected property, it isn’t sent to the front to be persisted. Assign it in your mount method and store it in the session, and pull it back from the session in your hydrate method.