Facing issues with Global Scope on subsequent request (hydrate)

I am facing an issue using global scope,

I am working on a multi-tenant application, I need to scope data base on the current tenant/company.

Tenant/Company is in the request which can access like so “request()->company()”

Everything works great with Controllers and Blade, now upgrading my application to Livewire

The scope works very on the first request, I got knock off on subsequent request with this error

    TypeError
    Argument 1 passed to App\Tenant\Scope\TenantScope::__construct() must be an instance of 
    Illuminate\Database\Eloquent\Model, null given, called in 
    D:\laragon\www\vistate\app\Tenant\Traits\ForTenants.php on line 19 

To reproduce this I have the following

<?PHP
namespace App\Tenant\Scope;

    use Illuminate\Database\Eloquent\Builder;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\Scope;

    class TenantScope implements Scope

    {

        protected $company;

        public function __construct (Model $company)
        {
            $this->company = $company;
        }

        public function apply(Builder $builder, Model $model)
        {
            return $builder->where($this->company->getForeignKey(), '=', $this->company->id);
        }

    }

Are you using the latest version of Livewire: Yes ( V2.4.1)

Do you have any screenshots or code examples:

Here is my Trait

    <?php

    namespace App\Tenant\Traits;

    use App\Tenant\Observers\TenantObserver;
    use App\Tenant\Scope\TenantScope;

    use App\Tenant\Manager;

    trait ForTenants

    {
        public static function boot()
        {
            parent::boot();
            $manager = app(Manager::class);
            static::addGlobalScope(
              new TenantScope($manager->getCompany())
            );

            static::observe(
                app(TenantObserver::class)
            );
        }

    }

so basically the active tenant is set in the request so it can be accessed throughout the application like so request()->company()

On first load, everything works fine but thereafter ( hydrate) request()->company() returns null value

Please any advise heads up how to resolve this

Thanks a lot in advance

protected $company; 
public function __construct (Model $company) 
{ 
      $this->company = $company; 
} 
public function apply(Builder $builder, Model $model) 
{ 
      return $builder->where($this->company->getForeignKey(), '=', $this->company->id); 
}

Check this 2 things.
Try change protected to public the company property. In Livewire, as long as I know, protected and private don’t persist data.
In the apply method (maybe this is irrelevant but checked instead) you make a comparison to the same company instance

public function apply(Builder $builder, Model $model) 
{ 
      return $builder->where($this->company->getForeignKey(), '=', $this->company->id); 
}

I think you need compare the $this->company->getForeignKey(), ‘=’, $model->id, as you are passing $model instance as parameter?

Thank you very much for your reply,

what I have in mind is when a user visits domain.com/admin/company, get and set the company in the session so in my controller I can
Blog::all() //the scope will intervein and find the Model where the foreign key is equal to the current tenant id
Blog::create([
‘title’ => …,
‘content’ => …,
]) //i don’t have to pass the company id as well, there is an observer to get that in place,

It is like a Saas CMS
This works well with Controller and blade and before i was thinking of Inertia js which It works fine as well but we don’t have Vue Js developer in our team, that is why we are thinking of using Livewire over Inertial Js.

I understand what you’re doing, I’m dev a Saas app with Milti-tenant but using Tenancy and working fine with Livewire. Sorry if I can help you more on this issue

Thanks so much for the help I figured out a workaround,
I have the Tenant Id in the request, there is no need to pass the tenant model,
I just reach out for the tenant_id in the request and it works fine

thanks again for your support

1 Like