I propose we move to deprecate the $defer property on service providers. In my experience, there's a bit of confusion around the property (what it does, how it works, and what else it needs). People will sometimes forget to implement the provides method, causing cryptic errors.
In place of this property, we'd have a Deferred interface that each service provider can implement, which would look a bit like this (typehint optional, of course):
interface Deferred
{
public function provides(): array;
}
A deferred service provider would then end up looking like this:
class RiakServiceProvider extends ServiceProvider implements Deferred
{
// ...
public function provides()
{
return [Connection::class];
}
}
The only method that'd need changing would be \Illuminate\Support\ServiceProvider::isDeferred, and it'd end up looking like this during the deprecation period (5.8?):
public function isDeferred()
{
return $this->defer || $this instanceof Deferred;
}
After the deprecation period, we could change it over to only have the instanceof check left.
This way, we avoid cryptic errors like Unresolvable dependency resolving [Parameter #0 [ <required> $foo ]] when the provides method isn't implemented. Instead, the user will get an error that the method should be added.