Comments (20)
I'm not sure how I feel about this. It strikes me that classes built with this annotation would be bound to the DIC, which isn't want we want.
If the issue you're trying to address is circular dependencies, is there anyway to we can tweak setter injection to prevent this loop? For instance, this is possible when bootstrapping by hand, but not possible in the DIC:
<?php
$a = new A();
$b = new B($a);
$a->setB($b);
If the issue is lazy dependencies, have you considered adding a lazy
option to Reference
and generating something like a Doctrine proxy object for that reference?
<?php
class Lazy_MyDependency extends MyDependency
{
private $__symfonyContainer;
private $__symfonyObject;
private $__symfonyLoaded = false;
private function __symfonyLoad()
{
$this->__symfonyObject = $this->__symfonyContainer->get('my_dependency');
$this->__symfonyLoaded = true;
unset($this->__symfonyContainer);
}
// proxy public methods...
}
from symfony.
I prefer auto wiring, over this solution.
from symfony.
I'm still not convinced. This would require you design your classes for vertical reuse, and awkwardly at that.
from symfony.
I think the amount of code saved is minimal, especially since you could also do the assignment inside the constructor at which point you are not even saving lines anymore. Furthermore this would lead to cases where you get errors on lines that do not match your original code.
-1
from symfony.
You cannot do this in the constructor as you get the container through as setter when extending ContainerAware.
from symfony.
Ah, right of course. Even still I think the lines saved is minimal and the debugging confusion makes this a no go for me. Debugging generated code is just a nightmare.
from symfony.
i am fine with generated PHP code for routes and the container since i usually shouldnt debug them, but for a controller its just not a good idea .. even if the line number if just off by a few lines its annoying. also it doesnt solve everything i am trying to solve ..
from symfony.
yes they will .. i was more talking about the final class .. but i guess one can just ignore that generated controller in stack traces, since actual errors should only occur on the abstract class.
from symfony.
OK, just to clarify things:
-
yes the original class stays intact and it can be expected that any bugs will be in the original class and not the generated one. so the concerns i raised where largely irrelevant
-
the ContainerWrapperBundle addresses two issues of which this approach only solves the first one: the first issue is being able to prevent hardcoding of the service id, the second is preventing uncontrolled access to the container in order to maintain an overview of what dependencies a service actually has. so as long as the entire container is still exposed within the service the second issue is not solved by this.
That being said, the ContainerWrapperBundle does provide a mode that in case there are no mappings of services can optionally remove the wrapper based on a configuration setting. This enables using the wrapper only during development and relying on the actual Container in production to reduce overhead. Now since this approach does solve the mapping, this "optimization" becomes even more feasible.
That being said, somehow I still have a negative gut feeling, but its not a full -1 anymore :)
from symfony.
Continuing my monolog. One thing that seems to be missing is a way to define a default service id, this would make this viable for non service Controllers
abstract class MyController
{
/**
* @MethodInjection(default="request")
* @return Symfony\Component\HttpFoundation\Request
*/
abstract function getRequest();
}
from symfony.
return Request::fromGlobals();
not sure what use case you are trying to illustrate here ..?
from symfony.
One question more, what makes this better than simple property injection? I mean is the "advantage" just that it uses the injected container? If so I would say the main use case are "lazy people" that dont really care at all about the concept of the DIC etc and therefore would probably just as well or even better be served via property injection with similar capabilities for defining a default service in an annotation + ability to redefine the actual dep via a service definition.
from symfony.
Defining an abstract method that provides a dependency is the opposite of dependency injection. We should not be encouraging people to design their classes in this way; it's not practical outside of this feature.
from symfony.
If I am reading this correctly it sounds like this would require generating code for Controllers. It also sounds like this wasn't happening before. If this is the case, would code be generated for all Controllers or would it only be generated for Controllers that need Method Injection?
What effect would this have on other services that may try to do Method Injection? Would they get base classes created for them as well?
from symfony.
Hi all, sorry to participate to the discussion in a probably unqualified manner. I am a big fan of "magic" behaviours like autowiring, as mentioned in a blog post of mine a few days ago (which lsmith was so kind to writing an detailed answer for. Unfortunately available in german only due to my sinister english skills (http://bit.ly/jWOfvO).
Besides all pros and cons mentioned above which i will have to read again very carefully to understand the drawbacks and undesired side effects, i want to suggest a probably (really plain) solution to avoid potential flawy or hard-to-debug code generation: A way to assign dependencies from outside to protected/private members could be using the built-in Reflection API by calling the ReflectionMethod/Property::setAccessible() method. This would probably imply an extension to the DIC and a performance drawback for sure (approximately twice (correction: 5! :/) the time a "regular" instance tree initialization would take, according to this post: http://bit.ly/13za52 But understanding autowiring as what i consider it to be this should be no showstopper because it would only affect "a handful" of instances (in contrast to e.g. hundreds or thousands of Doctrine ORM entities that potentially) are instanciated at runtime).
Nevertheless a +1 from me in general for this feature, mainly to gain API transparency and out-of-the-box IDE code-completion (respectivly what is used to be called "out-of-the-box" when dealing with PHP :D)
Thank you all for your hard work and best regards!
from symfony.
How does this make code completion easier in an IDE vs. doing property injection? I've seen a couple of people mention this. It seems like it should be the same (I get code completion already from @var annotation).
Is it in the case that the property wants to be private and the concrete class shouldn't have access to the actual property? Or am I missing something else?
from symfony.
You are absolutely right, you can gain code-completion through the current mechanisms to by e.g. annotatin\g vars like this (this works for at least the netbeans IDE):
/** @var $em \Some\Entitiy\Manager\Implementation **/
$em = $this->get('some.really.long.service.identifier);
Correct me if i am wrong, but i consider the "default", de-facto-standard syntax for PHP Doccomments beeing like this:
/**
- An entity manager
- @var \An\Entity\Manager $em: This is my entity manager
*/
private $em;
But this will not work at any scope, for local variables like the one fetched out of the DIC you'll have to use the special syntax.
With autowiring, you would have the "standard" confortable look-and-feel of members at any visibility, and even mutators may be annotated in a way so that they may be used "as usual":
/**
/**
- Does something.
* - @Inject(resource="a.another.member.implementation")
- @return \A\Returnvalue
*/
public function setAnotherMember(\Another\Member $member)
{
return $member.getAReturnValue();
}
This seems to be a clean way to wire my classes, and the dependencies stay "extensible" in the way that they can be easily replaced in the DIC definition.
I admit that the above mentioned "getter"-injection seems to be a bit complicated for me, its behaviour may be a little unforseenable. But setter injection is a well known pattern, or not?
With the proper "magic methods and brain fucking" DIC implementation, it probably may be possible to even inject into private and protected methods and properties - i don't see any dawbacks from there, because the DIC anyway is the "god of dependencies". What the DIC is allowed to do, the concrete API user must not be allowed to do.
But the bundle developer must be aware that the DIC may override private properties... May that be a problem?
//
Addendum: In the case of Property injection, you still have to know the service name - this is a slightly annoying thing for symfony beginners. But in the case of Setter-Injection, you even can analyze the method signature an compare the interface name to the concrete implementation of the service definition - so you'll have had a "real" java/spring like autowiring feature. And this would be a really amazing feature: You gain the ability to identify the dependency through the interface ("interface injection"), not through the service name.
And sorry - speaking about code-completion, but beeing to dumb to define markdown code-blocks :D
from symfony.
I have some ideas on Property Injection. Shall I elaborate?
from symfony.
Hello guys, I am also concerned with easy dependency injection and service definitions for advanced users who want to take full advantage of the power of the DIC, and that want to define their controllers as services (and not directly inject the container into their controllers). I have developed a bundle that enables annotation-based dependency injection for Symfony2 applications.
You can then come to this:
<?php
use LoSo\LosoBundle\DependencyInjection\Annotations as DI;
/** @DI\Controller */
class UserController
{
/**
* @var Doctrine\OROM\EntityManager $em
*/
private $em;
/** @DI\Inject("doctrine.orm.entity_manager") */
public function __construct($em)
{
$this->em = $em;
}
// ....
}
You can check the code on my Github repository and have a look to the documentation to let me know what you think about this.
from symfony.
It did not leave me in peace, thus i had to give it a try by myself and spend a weekend. I am aware of the fact that the general discussion does not affect the current core-development team (or does it?) so i am not sure if this is the right platform for discussing it - so forgive me and ignore my post if you feel unconcerned. Perhaps - if anyone is interested - may we meet at another location to discuss this features?
@loicfrering i love the approach as it provides some neat shortcuts for defining controllers as services - luckily the framework´s routing system supports that. Thanks for your great work on that! I have chosen a similar solution to define services and injecting dependencies by annotations, but in contrast to your code i wanted it to be more "convention driven" - merly to get rid of recalling service ids.
It is only a prototype, and the rules to resolve dependencies are not elaborated well. But a tiny demo works (might be buggy as ...:(), and the documentation explains the possiblities and purposes. It must be seen as a case study for investigating use cases, not as a solution design document for "the greatest autowiring stuff that´s ever been seen".
// The link to the repo:
https://github.com/joshiausdemwald/AutowiringBundle
I would love to hear comments about it. Thank you!
from symfony.
Related Issues (20)
- Messenger worker going to "idle" state without exit code HOT 1
- Deprecation in YAML parser HOT 1
- Fatal error in CsvEncoder
- Intl has Kosovo in DENYLIST HOT 2
- [Security][Framework] Use Firewall Settings to get UserProvider Service for Request
- After Upgrading to Symfony 7 no client request in unit test setup function possible
- [AssetMapper] importmap:install silently fail but say everything is ok on prod
- [DIC] Error when a service cannot boot: we unregister the wrong service
- Command: Adding argument called 'command' makes other args/options unreadable HOT 3
- If PUT method in twig, form isn't submitted HOT 7
- Mailer component and html() call -incompatible with simple_html_dom library ?
- symfony/property-access 6.4.6 breaks magic methods HOT 13
- Injecting all tagged services in a service by variadic constructor HOT 2
- [Validator] Passing Constraints to Object similar to Assert\Collection HOT 6
- [Mailer] Handle null & empty to/cc/bcc/reply-to addresses
- [Serializer] Restrictions HOT 4
- Path is not readable - mime\Part\TextPart checks if a directory is a directory and then throws HOT 5
- [Messenger] schema assets filter causes TypeError HOT 7
- [Cache] RedisTrait doClear with ext-redis int overflow HOT 2
- [Serializer] Inconsistent Naming of First Argument in normalize() Method between NormalizerInterface and Serializer Class
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from symfony.