Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[DependencyInjection] Add#[AutowireMethodOf] attribute to autowire a method of a service as a callable#54016

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekasnicolas-grekas commentedFeb 20, 2024
edited
Loading

QA
Branch?7.1
Bug fix?no
New feature?yes
Deprecations?no
Issues-
LicenseMIT

Let's take a controller for example, with one action that has this argument:

        #[AutowireMethodOf(CommentRepository::class)]        \Closure$getCommentPaginator,

The proposed attribute tells Symfony to create a closure that will callCommentRepository::getCommentPaginator(). The name of the method to be called is inferred from the name of the parameter.

This is already doable with this syntax, so that the proposed attribute is just a shortcut for this:

        #[AutowireCallable(service: CommentRepository::class, method:'getCommentPaginator')]        \Closure$getCommentPaginator,

Using this style allows turning e.g. entity repositories into query functions, which are way more flexible. But because the existing syntax is quite verbose, i looked for a more concise alternative, so here we are with this proposal.

Benefits:

  • Increased Flexibility: Allows developers to inject specific methods as Closures, providing greater control over what functionality is injected into
  • Improved Readability: By using the attribute, the intention behind the dependency injection is made explicit, improving code clarity.
  • Enhanced Modularity: Facilitates a more modular architecture by decoupling services from direct dependencies on specific class methods, making the codebase more maintainable and testable.

Because we leverage the existing code infrastructure for AutowireCallable, if I declare this interface:

interface GetCommentPaginatorInterface{publicfunction__invoke(Conference$conference,int$page):Paginator;}

then I can also do native types (vs a closure) without doing anything else:

        #[AutowireMethodOf(CommentRepository::class)]        GetCommentPaginatorInterface$getCommentPaginator,

pounard and ging-dev reacted with thumbs up emojilchrusciel, alexandre-daubois, Coderberg, OskarStark, kbond, ging-dev, and gilles-g reacted with heart emoji
@GromNaN
Copy link
Member

What is the reason to create a new attribute instead of makingmethod optional?

@nicolas-grekasnicolas-grekas changed the title[DependnecyInjection] Add#[AutowireMethodOf] attribute to autowire a method of a service as a callable[DependencyInjection] Add#[AutowireMethodOf] attribute to autowire a method of a service as a callableFeb 20, 2024
@nicolas-grekasnicolas-grekasforce-pushed thedi-autowire-method-as-callable branch from963b4d6 to8b85b8fCompareFebruary 20, 2024 20:09
@nicolas-grekas
Copy link
MemberAuthor

What is the reason to create a new attribute instead of making method optional?

Because method is already optional and it currently means__invoke, so that would be confusing.
A new attribute makes it explicit that some convention is used also IMHO (inferring the name of the method from the name of the parameter)

@alexandre-daubois
Copy link
Member

alexandre-daubois commentedFeb 20, 2024
edited
Loading

Really subjective point of view here, I definitely see an improvement of "instant understanding of what's being done". I think having this "alias attribute" helps to get what's happening at first sight, where the existing notation needs a bit of reflection before getting it.

It feels more human friendly to me

Fan2Shrek and OskarStark reacted with thumbs up emoji

@Kocal
Copy link
Member

What are the benefits aboutAutowireMethodOf andAutowireCallable, versus directly injectingCommentRepository?

@OskarStark
Copy link
Contributor

Only one con IMHO, if you refactor the method name via IDE this code breaks, I know it’s the same problem for the long attribute version. Not sure I would use it, because if you have no tests and even with static analysis this bug can go to prod. Sounds like a footgun but indeed nice DX

lyrixx, alexandre-daubois, alamirault, GromNaN, lchrusciel, and chalasr reacted with thumbs up emoji

@OskarStark
Copy link
Contributor

@Kocal my repositories are final so I cannot mock them, so I would need an interface. This way you don’t need an interface, can have a final class and you can easily test it.

@nicolas-grekas
Copy link
MemberAuthor

versus directly injecting CommentRepository

think about testing a service that has CommentRepository as a dependency: you cannot test it without having a database or without heavy mocking. Query functions are just trivial to replace instead.

OskarStark reacted with thumbs up emojismnandre reacted with heart emoji

@Kocal
Copy link
Member

Kocal commentedFeb 20, 2024
edited
Loading

Hum alright, I can understand the issue, but then doesn't it make sense to create by yourself a invokable class that you can easily mock?

IINW you lose the autocompletion/static analysis by usingAutowireMethodOf/AutowireCallable no?

tsantos84 and GromNaN reacted with thumbs up emoji

@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedFeb 21, 2024
edited
Loading

doesn't it make sense to create by yourself a invokable class that you can easily mock

It's like invokable controllers vs action methods: everyone their preferences 🤷 Mine is this attribute because of the low verbosity: just write a repository, and still get decoupling without creating a myriad of class boilerplate.

you lose the autocompletion/static analysis by using AutowireMethodOf/AutowireCallable no?

@param Closure(Conference, int): Paginator $getCommentPaginator to the rescue in my example (or inline@var Paginator $result)). The attribute doesn't introduce this concern also since the current alternative works the same.

Only one con IMHO, if you refactor the method name via IDE this code breaks

true with the current tooling, but this is fixable since the tools can very well be taught about the attribute. On this topic also the current situation is similar and the proposed attribute doesn't bring anything new.

OskarStark, Kocal, and kbond reacted with thumbs up emoji

@Kocal
Copy link
Member

Alright thanks for the explanations :)

@smnandre
Copy link
Member

You mentionned "query" but -naive question- would this work with setters / persisters too ?

Could this work ?

publicfunction__invoke(    #[AutowireMethodOf(CommentRepository::class)]\Closure$saveComment,    #[MapRequestPayload]Comment$comment,) {$saveComment($comment);}

@nicolas-grekas
Copy link
MemberAuthor

@smnandre yes of course

smnandre reacted with heart emoji

@nicolas-grekasnicolas-grekasforce-pushed thedi-autowire-method-as-callable branch 2 times, most recently from840e2f4 to139cc14CompareFebruary 22, 2024 12:57
@nicolas-grekas
Copy link
MemberAuthor

PR updated with better error handling and a test case.

@nicolas-grekasnicolas-grekasforce-pushed thedi-autowire-method-as-callable branch from0dface6 todbd45e3CompareFebruary 23, 2024 14:55
@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedMar 15, 2024
edited
Loading

FTR, if I define this interface:

interface GetCommentPaginatorInterface{publicfunction__invoke(Conference$conference,int$page):Paginator;}

Then I can also do native types (vs@param + closure) without doing anything else:

        #[AutowireMethodOf(CommentRepository::class)]        GetCommentPaginatorInterface$getCommentPaginator,
smnandre, GromNaN, and ging-dev reacted with heart emoji

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@kbondkbondkbond approved these changes

@OskarStarkOskarStarkOskarStark approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
7.1
Development

Successfully merging this pull request may close these issues.

8 participants
@nicolas-grekas@GromNaN@alexandre-daubois@Kocal@OskarStark@smnandre@kbond@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp