Back to writing
Laravel Jun 16, 2025 · 3 min read

Fixing Laravel IDE Helper for Multi-Tenant Setups with Stancl Tenancy

Laravel IDE Helper generates model properties from the landlord database — which doesn't have your tenant tables. One Artisan command fixes that.

Bright Nkrumah

Bright Nkrumah

Senior Software Engineer · Kumasi, Ghana

Fixing Laravel IDE Helper for Multi-Tenant Setups with Stancl Tenancy

While Laravel IDE Helper works great for standard applications, things break down in multi-tenant apps — especially when tenant databases differ from the landlord. Here's how I got it working with Stancl Tenancy.

I have used Barry's Laravel IDE Helper in a lot of my projects. PHPStorm's Laravel Idea plugin is also excellent, but for those who don't want a paid option, IDE Helper is the go-to. What I particularly like is how it adds database column names as PHPDoc properties on Eloquent model classes — which eliminates a significant class of errors that PHPStan/Larastan would otherwise flag.

It worked great until I needed it in a multi-database multi-tenant application with a landlord database and multiple tenant databases (using stancl/tenancy). The way this package works:

  • The landlord database is set in .env as the main connection
  • When a request comes in, the package reads the domain from the landlord database, identifies the tenant, and switches context to the tenant's database

The problem

When I ran php artisan ide-helper:models -W, the column annotations in my Eloquent models were wrong. After some investigation, I realised IDE Helper was reading from the landlord database — which doesn't contain the tenant tables. The actual model fields live in the tenant databases, but since tenancy was never initialised during the command, IDE Helper never saw them.

I looked through the IDE Helper configuration but found nothing to point it at a different connection per model. So I wrote a workaround.

The fix: a custom Artisan command

<?php

declare(strict_types=1);

namespace App\Console\Commands;

use App\Models\Tenant;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;

class GenerateTenantIDEHelper extends Command
{
    protected $signature = 'tenancy:ide-helper';

    protected $description = 'Generate IDE Helper annotations using a tenant database connection';

    public function handle(): void
    {
        $tenant = Tenant::first();

        if (! $tenant) {
            $this->info('No tenants found. Exiting.');
            return;
        }

        $this->info('Initialising tenant context for IDE Helper generation...');

        tenancy()->initialize($tenant);

        Artisan::call('ide-helper:generate');
        Artisan::call('ide-helper:meta');
        Artisan::call('ide-helper:models', ['-W' => true]);

        tenancy()->end();

        $this->info('IDE Helper generation completed.');
    }
}

Run it with:

php artisan tenancy:ide-helper

The logic is straightforward:

  1. Find any available tenant — it doesn't matter which one, they all share the same schema
  2. Initialise tenancy with that tenant, switching the active connection to the tenant database
  3. Run the three IDE Helper commands — they now read from the tenant database and see all the actual columns
  4. End tenancy, restoring the landlord connection

What each command does

ide-helper:generate

Generates _ide_helper.php with autocomplete stubs for Laravel facades, helpers, and macros. Helps your IDE understand dynamic magic methods.

ide-helper:meta

Generates .phpstorm.meta.php, which helps PHPStorm understand service container bindings and app()->make() calls — useful when working with dependency injection.

ide-helper:models -W

Scans your Eloquent models and writes their database columns directly into the class files as @property PHPDoc annotations. The -W flag writes to the files rather than generating a separate helper file. This is the one that fixes PHPStan complaints about unknown model properties.


The full command is available as a Gist on GitHub.

TL;DR: If Laravel IDE Helper is pulling fields from the wrong database in your multi-tenant project, initialise a known tenant before running the ide-helper commands. One custom command, and your model annotations will reflect your actual tenant schema.