Question

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?

Was it helpful?

Solution

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 ).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top