-
Notifications
You must be signed in to change notification settings - Fork 11.1k
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 |
Agreed, that seems odd to me. I don't see any reason to use static function and passing the instance itself as first parameter. Using |
@taylorotwell |
@rudiedirkx Welcome to Taylor's favorism in action: https://mastodon.online/@shaedrich/113550013196602259 |
@rudiedirkx @shaedrich when you maintain a framework, choices have to be made—sometimes, it's not the right time to implement something, and sometimes, the implementation is not good enough. I also have many PRs closed without explanations: contributing to popular open-source software is like that. It's hard on the maintainers too. Please don't hold grudges because of that. |
@innocenzi Sorry, but I see that differently. Taylor should communicate clearly. PRs should not be closed without giving a reason. Copy-pasting a generic response is not a reason. |
I also find the process frustrating. Recently, a PR was merged that added support for using the cache for password resets, event though 6 days before I posted a PR that expanded the password resets functionality to allow for custom drivers (a more flexible solution). The newer PR was merged before mine, so it didn't make sense to merge mine. However, I understand why it was done, like I said, it would have caused a lot of hassle as there was already something there doing part of what mine did. I also understand that writing a lengthy response to every PR that fully conveys the exact reasoning isn't viable. It's also NOT favouritism at all. I'd say that at least 75% of my PRs to Laravel are merged without issue or question, but 25% of them will often receive a generic response. It's the way things are, no point complaining about it. |
Your original PR was extremely limited and inflexible, adding a hard-coupled and hard-coded reference to a very specific use-case, without considering the wider problem and solution. This PR was based on my original work, which I couldn't complete, and it solved the same problem, but for many, many use-cases with flexibility to work for yet unknown use-cases. That is not to imply that your PR was bad, but, it's hopefully a good indicator as to why the PR may have been rejected. |
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: