-
Notifications
You must be signed in to change notification settings - Fork 10.9k
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
[11.x] Add support for acting on attributes through container #51934
[11.x] Add support for acting on attributes through container #51934
Conversation
This real world test doesn't work for me. My Also, I wonder if this would feel more natural if the attribute class itself had a method that did the resolution (receiving the attribute and container instance) instead of having to bind a <?php
namespace App;
use Attribute;
use Illuminate\Contracts\Container\ContextualAttribute;
#[Attribute(Attribute::TARGET_PARAMETER)]
class ConfigValue implements ContextualAttribute
{
/**
* Create a new class instance.
*/
public function __construct(public string $key)
{
}
} <?php
namespace App\Providers;
use App\ConfigValue;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
$this->app->whenHas(ConfigValue::class, function ($attribute) {
return config($attribute->key);
});
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
}
} <?php
namespace App;
use App\ConfigValue;
class Something
{
/**
* Create a new class instance.
*/
public function __construct(
#[ConfigValue('app.timezone')]
public string $value
)
{
}
} |
The idea behind keeping the two separate was to allow for more flexibility. It would be much easier to override the behaviour, that it would if it was part of the attribute. |
The implementation didn't work with primitives, but I just fixed that and added relevant tests. Good catch :)
I like the idea! I added support for this, in addition to
Fair point. I'm not sure what should take precedence between In the current implementation, @taylorotwell do you have an opinion on this? |
45e0a0c
to
7b595ff
Compare
I think Added support for "after" directly on the attribute. Also added built in |
@innocenzi There were some modifications I was going to make to #51115, but I've been ill for the last couple of days, primarily:
Though I see now that @taylorotwell merged this while I was writing, I'll create a separate PR with the changes. |
@innocenzi I know this has long been merged, but I've noticed a bit of an issue with the 'resolve' method approach. You're calling |
This pull request adds support for resolving instances marked by attributes as well as acting on resolved instances marked by attributes.
Resolving instances through attributes
This is done by creating an attribute that implements
ContextualAttribute
, and binding it to the container viawhenHas
:When an attribute is bound through
whenHas
, any class constructor parameters marked with the corresponding attribute will be resolved by the associated closure:For context on this specific example, you may read the description of the previous pull request.
Note
The pull request was updated to also support resolving with a
resolve
method on the attribute itself instead of having to bind awhenHas
callback:Acting on resolved instances through attributes
The other scenario this pull request helps with is acting on resolved dependencies or classes through an attribute.
This is similar to the previous feature, except the container will resolve the dependency first, so you don't have to do it yourself. This is preferable than using
whenHas
when the dependency is already bound to the container—for instance, in a third-party package—and you want to further configure it. You may also configure multiple callbacks using this method.Using the example above, the following class will have its
Connector
class resolved first, and the "after resolving attribute" callback called after, so that the connector may be configured accordingly:Additionally, you may also add an attribute directly to a class. The following example implements an attribute that calls the
booting
method when a class is resolved:Note
The pull request was updated to also support the "after" callback on the attribute itself instead of having to bind a
afterResolvingAttribute
callback: