Yesterday in accordance with the manual tutorial, to write a auth extension, in accordance with the principle of package independence, I do not want to write the Auth::extend () This method in start.php, no doubt, I chose to register the extension driver in the service Provider register () method. However, it backfired ...
Find problems
When I wrote this in the Loauthserviceprovider:
The
code is as follows:
Public Function Register ()
{
//
auth::extend (' Loauth ', function ($app) {});
}
Error
The
code is as follows:
call to undefined method Illuminatesupportfacadesauth::extend ()
Find out why
At that time was puzzled, find the reason, suspicion is auth not registered? Check discovery is registered, because it can be used in routing, PHP artisan clear-compiled useless, baffled, and even suspected that I accidentally modified the core class, but also downloaded a laravel package, the problem remains.
Tossing all night, and finally I stared at the $defer attributes of the Authserviceprovider.
According to the manuals and notes, we know that the $defer property is used to delay loading the service provider, and that the straightforward point is to delay the execution of the Register () method, which only needs to be implemented with the provides () method. As an example:
The
code is as follows:
Public Function provides ()
{
return Array (' auth ');
}
This is the method in the Authserviceprovider, when the framework is initialized, the service provider is loaded sequentially, and if the service provider protected $defer =true then the provides () method is invoked. The array returned contains a service name that requires deferred loading, so that the register () method of the provider is invoked when we call Auth::method () in the routing, controller, or elsewhere.
Identify the crux of the problem
So here's the problem, since it's passive delay loading, which means that when I call the Auth class method, I should automatically instantiate the Auth class, and why I'm calling the method when I call it in Loauthserviceprovider, but it's OK in the route.
I suspect that because of the priority problem, it is possible that when the framework registers Loauthserviceprovider::register (), the Auth has not been marked as deferred loading, which creates a sequential problem, Any immediate-loaded service provider cannot invoke a deferred-loading service in the Register method.
After research, we find the evidence in the core code successfully illuminatefoundationproviderrepository
The
code is as follows:
Public Function load (application $app, array $providers)
{
//... Omit
//We'll go ahead and register all of the eagerly loaded providers with the
//application so their services can is registered with the application as
//a provided service. Then We'll set the deferred service list on it.
foreach ($manifest [' eager '] as $provider)
{
$app->register ($this->createprovider ($app, $provider));
}
The
//delay load tag is immediately after the service is loaded
$app->setdeferredservices ($manifest [' deferred ']);
}
The way to solve it
Although the problem is found, but does not mean that the problem is resolved, to modify the core code is not a wise choice, so only in our own bag to find a way, a solution is as follows:
The
code is as follows:
Public Function Register ()
{
//
$authProvider = new Illuminateauthauthserviceprovider ($this->app);
$authProvider->register ();
auth::extend (' Loauth ', function ($app) {});
}
Since Auth has not yet been registered, then we manually call its register method to help it register.
The above is the entire content of this article, I hope you can enjoy.