Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to register a Expression Language in Symfony

Tags:

php

symfony

I already created a provider with a security function. Following the doc, i created my own ExpressionLanguage class and registered the provider.

namespace AppBundle\ExpressionLanguage;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;

class ExpressionLanguage extends BaseExpressionLanguage
{
    public function __construct(ParserCacheInterface $parser = null, array $providers = array())
    {
        // prepend the default provider to let users override it easily
        array_unshift($providers, new AppExpressionLanguageProvider());

        parent::__construct($parser, $providers);
    }
}

I'm using the same function lowercase that is in the doc. But now, i have no ideia how to register the ExpressionLanguage class to be loaded in my Symfony project.

I get this error every time i try to load a page with the custom function in the annotation:

The function "lowercase" does not exist around position 26.

I'm using Symfony 2.7.5.

like image 918
Iago Avatar asked Oct 30 '22 17:10

Iago


1 Answers

The tag security.expression_language_provider is only used to add language providers to the expression language used in symfonys security component, or more specifically in the ExpressionVoter.

The @Security-Annotation of the FrameworkBundle uses a different instance of the expression language, which has no knowledge of the language providers you created.

To be able to use custom language providers in the @Security-Annotation, I solved this using the following compiler pass:

<?php

namespace ApiBundle\DependencyInjection\Compiler;

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

/**
 * This compiler pass adds language providers tagged
 * with security.expression_language_provider to the
 * expression language used in the framework extra bundle.
 *
 * This allows to use custom expression language functions
 * in the @Security-Annotation.
 *
 * Symfony\Bundle\FrameworkBundle\DependencyInection\Compiler\AddExpressionLanguageProvidersPass
 * does the same, but only for the security.expression_language
 * which is used in the ExpressionVoter.
 */
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container)
    {
        if ($container->has('sensio_framework_extra.security.expression_language')) {
            $definition = $container->findDefinition('sensio_framework_extra.security.expression_language');
            foreach ($container->findTaggedServiceIds('security.expression_language_provider') as $id => $attributes) {
                $definition->addMethodCall('registerProvider', array(new Reference($id)));
            }
        }
    }
}

This way, the expression languages used by the ExpressionVoter and FrameworkBundle are both configured using the same language providers.

like image 129
mkraemer Avatar answered Nov 02 '22 11:11

mkraemer