Jeroen-G / autowire

🔌 Autowire and configure using PHP 8 Attributes in Laravel.
MIT License
21 stars 3 forks source link

Allow to use #[Autowire] on implemntations #10

Open Jurigag opened 1 year ago

Jurigag commented 1 year ago

So in our code we personally like to keep interfaces clean, we are using hexagonal architecture and all our service providers are kept in infrastracture code, and interfaces don't have any framework related code. So is it possible to maybe allow marking implementations with #[Autowire] and then it could get interfaces of this class and bind them to the container? Also as optional parameter maybe we could tell there which exactly interface we want to bind in case of multiple interfaces.

Jeroen-G commented 1 year ago

First on a theoretical basis: I think you should see annotations not as infrastructure code, they are not a runtime dependency as explained by Matthias Noback in this article.

Secondly, a class can have multiple interfaces and having to define which of them is meant to be autowired is going a bit against the philosophy I had with this package. However, if you still strongly disagree with my theoretical argument above I am open to see a PoC that supports both ways of working. I don't need this myself right now so don't wait for me to write it 😇

Jurigag commented 1 year ago

Well I disagree about this. It still comes from third party library - we would need to exclude this namespace in deptrac, this is why this is Infrastracture code for us.

Also I agree about article, but this is a separate thing we are discussing here, you can move your doctrine annotations to xml file and don't have any annotations in DDD entities at all, so it's kind of best of two worlds. But I will try to prepare some PoC with PR.

Jeroen-G commented 1 year ago

Third party libraries does not strictly equal the infrastructure layer in all cases. However, if having my namespace in your domain is part of the pain point then your issue seems to resemble the discussion (and solution) in #4 and #5.

Jurigag commented 1 year ago

Personally I think it's still good idea to do my change, I think symfony also autowires it like this, for example if there is just one implementation of your interface - if everything is autowired you can just access interface and it simply works.

bitwise-operators commented 1 year ago

Let me join in this discussion, as my PR was mentioned. ;-)

I think symfony also autowires it like this, for example if there is just one implementation of your interface - if everything is autowired you can just access interface and it simply works.

That is exactly what this package does: By adding an #autowire attribute to an interface you're telling Laravel: "I have this interface that I'm going to depend on. I don't care where you get an implementation from, just do it."

If you put the #autowire attribute on the implementation, you break the chain of responsibility. Now the implementation decides whether or not the interface gets implemented, not the application. So your code depending on the interface is no longer certain of an implementation being provided.

You can safely autowire all your classes, and then still have multiple implementations. The Autowirer will pick the first option it comes across, but you're free to override that in your AppServiceProvider if you want to.