Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ModuleServiceProvider register singleton issue #1761

Open
xavi7th opened this issue Mar 14, 2024 · 1 comment
Open

ModuleServiceProvider register singleton issue #1761

xavi7th opened this issue Mar 14, 2024 · 1 comment
Assignees

Comments

@xavi7th
Copy link

xavi7th commented Mar 14, 2024

I am having a weird issue with one of my Module service providers.

In the register method of my ModuleServiceProvider I have this code

$this->app->singleton(GateContract::class, function ($app) {
      return new ModifiedGate($app, function () use ($app) {
        return call_user_func($app['auth']->userResolver());
      });
    });

My ModifiedGate class has the Conditionable trait.

In one of my codes I am using the conditionable when method on the Gate Facade like this.

Gate::when($this->user, fn($gate) => $gate->forUser($this->user))->inspect('policy', 'class')->allowed();

Now, before I updated to Laravel 10, everything worked perfectly. However after upgrading to Laravel 10, I am having an issue with the when method. I get this error Call to undefined method Illuminate\Auth\Access\Gate::when().

After hours of debugging I believe that the singleton bind in my ModuleServiceProvider is somehow not working. What is weird though is that I can verify that the code is being run. If I place a dd() inside the singleton bind, or before it, my code hits it. That tells me that at least Laravel is running the code to bind it. But it somehow does not stick as Laravel still resolves the original GateContract instead of my ModifiedGate.

After debugging further, I noticed that if I place the bind code in the register method of the default AppServiceProvider class, everything works fine. That means Laravel properly binds the singleton from the default AppServiceProvider class.

Another weird observation is this. If I manually add my ModuleServiceProvider class into the providers array of the app config file like the example below, it also works perfectly. Laravel recognises the singleton bind.

'providers' => ServiceProvider::defaultProviders()->merge([
    /*
     * Application Service Providers...
     */
    App\Providers\AppServiceProvider::class,
    . . .
    ModuleNameSpace\ModuleServiceProvider::class, // if this is added it works
  ])->toArray(),

This is weird because I thought Laravel auto-discovered Module ServiceProviders and there should be no need to manually register them. The fact that Laravel executes the singleton bind code even without the manual registration suggests to me that that is the case, so I can't figure out why I need the manual registration before Laravel accepts the singleton bind.

I have cleared the compiled files in bootstrap/cache folder. I have tried running artisan compile (and curious enough the ModuleServiceProviders are not listed in the compiled providers array🤔). I have tried adding the service provider to the extra laravel key of the Modules composer.json file (to force Laravel to auto-discover it). I have also tried removing it. All to no avail.

The only thing that works for now is doing the binding in the AppServiceProvider's register method, or keeping the code in my ModuleServiceProvider and manually registering my ModuleServiceProvider in app config providers array.

Any ideas what I could be doing wrong? If it will help, I can provide a link to the flareapp.io error.

Thank you for your time.

@dcblogdev dcblogdev self-assigned this Mar 18, 2024
@dcblogdev
Copy link
Collaborator

thanks for the detailed post, this will help me to dig into it further

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants