Define Symfony2 service with custom tags

1.5k views Asked by At

I have an image service in my Symfony2 application that resizes images. I want to be able to make this service configurable in such a way that it can take a number of parameters which indicate valid image sizes. E.g. This is my current service definition:

my.service.image:
    class: My\Service\ImageService
    arguments: ["@service_container"]

Somehow I would like to indicate a valid number of image sizes. I have looked into using Tags but I'm not sure if they are appropriate to use in this situation. In an ideal world I probably want to end up with something that looks like this:

my.service.image:
    class: My\Service\ImageService
    arguments: ["@service_container"]
    sizes:
        - { name: small, width: 100, height: 100 }
        - { name: medium, width: 100, height: 100 }
        - { name: large, width: 100, height: 100 }

What would be the best way to implement this and how to I make my service aware of the various "sizes"?

UPDATE:

I have made some progress but I'm still stuck on this issue. This is what I have accomplished so far.

I've used tags to implement the different sizes:

my.service.image:
    class: My\Service\ImageService
    arguments: ["@service_container"]
    tags:
        - { name: my.service.image.size, alias: small,  width: 100, height: 100 }
        - { name: my.service.image.size, alias: medium, width: 200, height: 200 }
        - { name: my.service.image.size, alias: large,  width: 300, height: 300 }

Trying to follow the cookbook documentation [1], I ended up creating a *CompilerPass class in my bundle:

namespace My\Bundle\MyImageBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

class ImageServiceSizeCompilerPass implements CompilerPassInterface {

    public function process( ContainerBuilder $container )
    {
        $definition = $container->get(
            'my.service.image'
        );

        $taggedServices = $container->findTaggedServiceIds(
            'my.service.image.size'
        );

        foreach( $taggedServices as $defintion => $attributes )
        {
            foreach( $attributes as $attribute )
            {
                $definition->addSize( $attribute['alias'], $attribute['width'], $attribute['height'] );
            }
        }
    }

}

The above is actually calling the addSize method on the service. I'm not sure if the above is correct but it seems to work OK.

The problem I'm now running into is that when in my application code I request my.service.image from the container it seems to instantiate it again rather then returning the instance it already created the first time.

Any insight would be much appreciated.

[1] http://symfony.com/doc/current/components/dependency_injection/tags.html

1

There are 1 answers

0
nixoschu On

I'm not sure what your exaclty is your use case but i want to give you the following hints

  • Are these images (their paths) saved as an attribute of an entity ? Then why not use Annotations at the entity directly?

  • If you really want to have this configureable then why not creating a real config out of it ?

  • If you want to pass something into your service (and not want to create a config) you could make paramters inside your yml file out of your sizes and pass them into your service or you just fetch the parameters from your service itself using $container->getParameter('NAME'); (assuming you have a container injected)

hope i could help, nixo