Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[RFC] - Not having constructors for service classes with annotations & traits #26915

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

Closed
oliverde8 opened this issue Apr 13, 2018 · 5 comments
Closed
Labels
DependencyInjection Feature RFC RFC = Request For Comments (proposals about features that you want to be discussed)

Comments

@oliverde8
Copy link

Q A
Bug report? no
Feature request? yes/maybe
BC Break report? no
RFC? yes
Symfony version x.y.z

Why ?

Generally speaking creating a cosntructor is not a problem. The issue is when you are extending existing services of "other" applications using symfony(Akeneo & Ez...). For exemple serviceA has a class looking like this :

<?php
class serviceA {
    protected $propertie1A; 

    public function __construct(InjectedService1A $propertie1A) {
        // ....
    }
}

We extend this service to change a particular behavior.

<?php
class serviceB extends serviceA {
    protected $propertie1B; 

    public function __construct(InjectedService1A $propertie1A, InjectedService1B $propertie1B) {
        // ....
    }
}

At this point if the maintainers of serviceA changes service A to add a new property you will need to change your serviceB. Which is why constructor changes are usually considered BC. I don't like extending services but when changing the behaviours of existing system sometimes it's the only choice.

Proposal

What I thought of is use annotations & trait to make it a bit magic

<?php
class serviceA {
    use AutoConstructTrait
    /**
     * @var InjectedService1A
     * @AutoConstructAnnotation()
     */
    protected $propertie1A; 
}

With the trait lookingsomething like :

trait AutoConstructTrait {
    public function __construct(...$args)
    {
        $class = get_class($this);
        $properties = AutoConstructAnnotation::getClassProperties($class);

        $count = 0;
        foreach ($properties as $field => $constrains) {
            if (isset($args[$count])) {
                // TODO validate value with constraints? using the type in @var. 
                $this->$field = $args[$count];
            } else {
                throw new \Exception("$class is expecting parameter $field");
                // TODO nice exception.
            }
            $count++;
        }
    }
}

Advantages/Disadvantages :
👍 No need to maintain the constructors
👍 I quite often see new developers putting logic that shouldn't be in constructors in constructors. This would make it less probable.

👎 : Having annotations for DI,
👎 : Instancing the class without the DI is harder as we have no idea what parameter it takes.

I think it's a interesting subject of discussion, it might be just a waste of time. Whad do you think?

@javiereguiluz javiereguiluz added DependencyInjection Feature RFC RFC = Request For Comments (proposals about features that you want to be discussed) labels Apr 13, 2018
@linaori
Copy link
Contributor

linaori commented Apr 13, 2018

Injections based on annotations have been rejected multiple times:

One solution is to use autowiring for your configuration, so you maintain less configuration wise. Design wise, use decoration. If that's not possible, make it possible via the vendor 😄

Edit: if you really, really, really want to venture into this territory, you can use the JMS DI Extra Bundle: https://jmsyst.com/bundles/JMSDiExtraBundle

@oliverde8
Copy link
Author

oliverde8 commented Apr 13, 2018

I really don't like the idea of having annotations on parameters, even less having annotations to configure the DI. I like a lot the current system as it is.

The annotations here are to decide which properties should be in the constructor. If we could avoid that I would be much happier. In other languages you could say that anything that is a final property should be in the constructor.

Auto-wiring does not not resolve the issue of maintaining the constructors. It resolve the issue of maintaining the service declaration(yml).

Maybe someone can have an idea to get this working without annotations and with less drawbacks. If not well we close it.

Edti : Indeed using decorations would be the best way, but for multi instance services that doesn't resolve the issue.

@ostrolucky
Copy link
Contributor

Symfony DI already supports automatic injections for setters if you annotate them. Not sure what exactly do you propose here.

@nicolas-grekas
Copy link
Member

nicolas-grekas commented May 7, 2018

If I understand well, serviceA would be provided by a vendor? IMHO, there is no way any reasonable vendor will design their classes this way.

@nicolas-grekas
Copy link
Member

Closing as that's not something we want to provide in Symfony.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DependencyInjection Feature RFC RFC = Request For Comments (proposals about features that you want to be discussed)
Projects
None yet
Development

No branches or pull requests

5 participants