ioleo
ioleo

Reputation: 4817

How to programically inject a dependency to N classes in Symfony2? Can I somehow inherit injected services?

In my app I am generating n number of classes. They all have the same skeleton and serve a similar purpose. They also share dependencies.

Instead of adding n entries in services.xml like so:

    <service id="acme.security.first_voter" class="Acme\SecurityBundle\Security\Authorization\Voter\FirstVoter" public="false">
        <tag name="security.voter" />
        <argument type="service" id="logger" />
    </service>
    <service id="acme.security.second_voter" class="Acme\SecurityBundle\Security\Authorization\Voter\SecondVoter" public="false">
        <tag name="security.voter" />
        <argument type="service" id="logger" />
    </service>

I'd like to simply add one entry like this:

    <service id="acme.security.base_voter" class="Acme\SecurityBundle\Security\Authorization\Voter\BaseVoter" public="false">
        <tag name="security.voter" />
        <argument type="service" id="logger" />
    </service>

and in each Voter simply add

use Acme\SecurityBundle\Security\Authorization\Voter\BaseVoter;

class FirstVoter extends BaseVoter

But that does not work.

I've seen Managing Common Dependencies with Parent Services, but it does not solve my issue, becouse it requires I add a

<service id="acme.security.first_voter" class="Acme\SecurityBundle\Security\Authorization\Voter\FirstVoter" parent="base_voter"/>
<service id="acme.security.second_voter" class="Acme\SecurityBundle\Security\Authorization\Voter\SecondVoter" parent="base_voter"/>

for each voter... but thats exacly what I'm trying to avoid, becouse n can be 5 or.. 500.

I've read some old Richard Miller blog posts about injecting a dependency into an interface, and all classes implementing that interface would "inherit injected dependencies" (also be injected that service). Thats exacly what I need! Unfortunately, this has been dropped for some reason and it does not work for Symfony2.3.

Is there any solution to my problem?

Upvotes: 1

Views: 246

Answers (1)

Nicolai Fr&#246;hlich
Nicolai Fr&#246;hlich

Reputation: 52513

You can well use parent services for this purpose.

You just have to register them all using a CompilerPass instead of adding each one manually.

Use the Finder component to search all bundle's i.e. Voter folder for classes extending your base voter - then register them in the CompilerPass.

Improve by caching your results for performance reasons :)


Or you use JMSDiExtraBundle

use JMS\DiExtraBundle\Annotation\Service;

/**
 * @Service("some.service.id", parent="another.service.id", public=false)
 */
class Voter extends BaseVoter
{
}

It basically does exactly that ( using a compilerpass ).

Upvotes: 2

Related Questions