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

lasse's avatar
Level 9

How can I refactor this multi tenant global scope?

I got this piece of global scope, and would like to get rid of the is_a() method which feels clunky but is needed. Reason being the first time the global scope receives a request object, the subdomain is not bound to a tenant model yet, and all I get is a string. On subsequent requests, the model is bound and I get the Tenant model. How can I fix this so that what the scope receives is consistent?

URL is like: tenant.app.dev

Thanks :)

<?php

namespace App\Scopes;

use App\Tenant;
use Illuminate\Support\Facades\Request;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class TenantScope implements Scope
{
    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        if (is_a($tenant = Request::route('tenant'), Tenant::Class)) {
            $builder->where($model->getTable() . '.tenant_id', '=', $tenant->id);
        }
    }
}

The output I get when I dump the $tenant variable in the apply() method of the scope is:

"tenant"

Tenant {#502 ▼
  #connection: "mysql"
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #attributes: array:8 [▶]
  #original: array:8 [▶]
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #events: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
  #guarded: array:1 [▶]
}

Tenant {#502 ▼
  #connection: "mysql"
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #attributes: array:8 [▶]
  #original: array:8 [▶]
  #casts: []
  #dates: []
  #dateFormat: null
  #appends: []
  #events: []
  #observables: []
  #relations: []
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
  #guarded: array:1 [▶]
}

Notice the string at the beginning. Why is it there?

0 likes
0 replies

Please or to participate in this conversation.