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

gvdspuy's avatar
Level 51

Global query scopes preventing seeding of model relationships

I am encountering a problem running a seeder on a model and its relationships. I have a global query scope that uses a session variable that does not exist in this context which causes the seeder to fail. Is there any way to bypass the global query scope when seeding? 'withoutGlobalScope' does not seem to work in seeders or factories or perhaps I'm not understanding how to use it in this context.

0 likes
11 replies
Sinnbeck's avatar

Can you show the global scope, the seeder and how you use it?

gvdspuy's avatar
Level 51

public function run() { Investigation::factory(10) ->hasContacts(5) ->create(); }

The queryscope is on the investigationContact model.

public function apply(Builder $builder, Model $model) { $builder->where('investigation_id', Session::get('investigation')->id); }

Sinnbeck's avatar

@gvdspuy How about doing this?

public function apply(Builder $builder, Model $model)
    {
        if (Session::has('investigation') {
            $builder->where('investigation_id', Session::get('investigation')->id);
        }
    }
gvdspuy's avatar
Level 51

The problem with that is that the query scope is there to prevent users accessing investigation contact records in an investigation they don't have access to as well as restricting data returned to the currently active investigation. Your solution would solve the seeding problem, but would bypass the security.

gvdspuy's avatar
Level 51

Nope - still gives the same error.

Your previous suggestion gave me an idea, however. Getting the seeder to create a temporary 'seeding' session variable that can be tested for in the query scope does work. The only negative here is that I now have development-specific code permanently in the production codebase. Not a deal-breaker I guess.

Sinnbeck's avatar

@gvdspuy Ah you would need to add it to the investigationContact factory then.. Sorry missed that.

Try adding this to its factory

public function configure()
    {
        return $this->afterMaking(function (investigationContact $contract) {
            $contract->withoutGlobalScopes();
        });
    }
gvdspuy's avatar
Level 51

Yes, the scope returns an error attempting to read the non-existent session variable. So the scope is still being called.

gvdspuy's avatar
gvdspuy
OP
Best Answer
Level 51

So here is a solution I came up with.

Investigation::factory(10)->create()->each(function ($investigation) {
    Session::put('investigation', $investigation);
    InvestigationContact::factory(5)->create();
 });

The InvestigationContact factory then populates the investigation_id foreign key from the session variable.

alternatively

Investigation::factory(10)->create()->each(function ($investigation) {
    Session::put('investigation', $investigation);
   InvestigationContact::factory(5)->create([
                'investigation_id' => $investigation->id,
            ]);
 });

It's not as pretty as just using ->has('contact'), but it works and doesn't require messing with the query scope. It seems to me that bypassing global query scopes in seeders/factories might be a useful feature that could be added to Laravel.

Please or to participate in this conversation.