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

inkarnation's avatar

Access session from global scope within service class

Hi! so within my application users may belong to a company (yet only one; in future during the login the user might choose the company to work on). Sure thing, all related objects/models relate to the company as well, so other users may access those as well (Assume, documents/appointments/... that belong to that company).

So to keep code clean I introduced global scopes on those company related models:

protected static function booted() {
    static::addGlobalScope(new CompanyScope);
}
class CompanyScope implements Scope {
    public function apply(Builder $builder, Model $model) {
        $builder->where('company_id', session(SessionKey::SESSION_KEY_COMPANY_ID));
    }
}

while the session key is set during login. Great thing and working perfectly.

I stumpled accross this neat repo: https://github.com/alexeymezenin/laravel-best-practices/, and started to migrate some logic into services.

class DocumentService
{
    private $docInstance;

    public function __construct(DocumentType $type)
    {
        $this->docInstance = Document::where('type', $type->value)->first();
    }

    public function nextNumber()
    {
        return $this->docInstance->getNextNumber();
    }
}

Documents are "numbered", but once my Controller tries to obtain the nextNumber(), the call fails, since $docInstance is null. The exception page tells me, that the query on Document is searching for company_id is null; so likely the service doesn't have access to the session scope. I guess "works as designed" but I am not able to cope with a new solution.

Does one of you has some hint how to approach/solve this issue?

Thanks!

0 likes
3 replies
Snapey's avatar

Its probably a timing issue, ie your service constructor runs before the session middleware

inkarnation's avatar

@Snapey thanks for your hint! I tried to google for some further informations in that matter and found a comment from taylor that I think goes into that direction: https://github.com/laravel/framework/issues/15072#issuecomment-242769373 . Having that, my question should likely change from "How to access the session within the service constructor?" to "What's a better way to approach that global scoping for users/companies?" Do you have some idea/hint? Or am I completely on a wrong track and should indeed switch to explicitely pass the company_id/object on every single service interaction (e.g. getNextNumber(Document $doc); getDocument(company_id), ....)?

Snapey's avatar

@inkarnation I would just use the global scope approach. Not sure what this service actually does for you (maybe this is a simplified example)

You don't say how this service is instantiated, but one option would be to pass it the company id in the constructor

Please or to participate in this conversation.