Skip to content
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

[WIP][Routing] Extended Expression Language in a routing component #10512

Conversation

mgiustiniani
Copy link

Q A
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets none
License MIT
Doc PR not yet
  • add tests
  • add docs
  • gather feedback for my changes

A new expression language engine in a routing component can't extended with new custom functions, in my project i need custom function in a route condition.

with this patch and a custom compilerpass in my bundle i can added my custom function (version_compare of php).
this feature work with symfony/routing >= 2.4

class OverrideServiceCompilerPass implements CompilerPassInterface
{
    public function process(ContainerBuilder $container){


        $definition = $container->getDefinition('router.default');

        $definition->addMethodCall('setExpressionLanguage',array(new Reference('examplebundle.routing_expression_language')));

    }
} 

a code of examplebundle.routing_expression_language is here:

class NewExpressionLanguage extends ExpressionLanguage
{

    protected function registerFunctions()
    {
        parent::registerFunctions();

        $this->register('compare', function ($version1, $version2, $operator) {
            return sprintf('version_compare(%s, %s, %s)', $version1, $version2, $operator);
        }, function (array $values, $version1, $version2, $operator) {
            return version_compare($version1, $version2, $operator);
        });
    }

}

@mgiustiniani mgiustiniani changed the title Extended Expression Language in a routing component [Routing]Extended Expression Language in a routing component Mar 22, 2014
@mgiustiniani mgiustiniani changed the title [Routing]Extended Expression Language in a routing component [Routing] Extended Expression Language in a routing component Mar 22, 2014
@mgiustiniani mgiustiniani changed the title [Routing] Extended Expression Language in a routing component [WIP][Routing] Extended Expression Language in a routing component Mar 22, 2014
@jakzal jakzal added the Routing label Mar 22, 2014
@lsmith77
Copy link
Contributor

how would one then parse out the relevant headers? ie. how would one then parse the version from a media type?

@mgiustiniani
Copy link
Author

a PR support only extension of expression language, after this PR you can inject an expression language service with injected services (ie. request, security.context etc...).

I need this PR for Versioning API with FOSRestBndle. with add version_compare function i can use a routing condition like this:

condition: "compare(request.attributes.get('version'),'1.1', '>')"

a request and context services is initialized by default

@merk
Copy link
Contributor

merk commented Mar 24, 2014

@lsmith77 seems like that part isnt actually a consideration here. I like the idea of being able to use version_compare in the routing definitions, but that leaves implementing parsing of version headers up to the user (which we could provide in FOSRestBundle)

@lsmith77 lsmith77 mentioned this pull request Mar 26, 2014
@mgiustiniani
Copy link
Author

i created an experimental bundle for this functionality
https://github.com/mgiustiniani/RestExtraBundle

if (method_exists($this->matcher, 'setExpressionLanguage')) {
$this->matcher->setExpressionLanguage($this->expressionLanguage);
}

return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong to me. It should just be return $this->matcher;.

@fabpot
Copy link
Member

fabpot commented Sep 23, 2014

Using method_exists() is not great, but it's probably the only way to keep BC here.

I like this PR. Besides my comment, can you add some tests to validate that the router actually works when injecting an expression language?

@mgiustiniani
Copy link
Author

Sure!

@mgiustiniani mgiustiniani force-pushed the feature-expressionlanguage-extension-for-routing-component branch from dd8dbcc to fd756bb Compare September 23, 2014 10:59
@mgiustiniani mgiustiniani force-pushed the feature-expressionlanguage-extension-for-routing-component branch from fd756bb to 52aa876 Compare September 23, 2014 14:52
@fabpot fabpot mentioned this pull request Sep 23, 2014
2 tasks
@fabpot
Copy link
Member

fabpot commented Sep 23, 2014

Thinking about this a bit more, I think this is not enough. If several bundles wants to add functions, it won't be possible as we are using inheritance here.

Instead, I think we need to create some kind of FunctionProviders that you can register on ExpressionLanguage instances`. That's what I've done in #12006.

@fabpot fabpot closed this Sep 23, 2014
@mgiustiniani
Copy link
Author

Multiple ExpressionLanguage is a good option but can create conflict with multiple expression language.
Imho, i create an another expression language class (that extend original expression language) with your new features and user can choose a prefer option. is a bad idea?

fabpot added a commit that referenced this pull request Sep 28, 2014
This PR was merged into the 2.6-dev branch.

Discussion
----------

Expression language extensibility

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #10512
| License       | MIT
| Doc PR        | not yet

The way we can add functions to an ExpressionLanguage instance is by using inheritance. #10512 tries to make the expression language in the routing flexible but using inheritance won't work when several bundles want to add functions.

So, this PR takes another approach to solve the problem globally.

Todo:

 * [x] add some more tests
 * [ ] add some docs

Commits
-------

7c24188 [FrameworkBundle] added a compiler pass for expression language providers
4195a91 [Routing] added support for custom expression language functions
1a39046 [Security] added support for custom expression language functions
79bcd52 [DependencyInjection] added support for custom expression language functions
184742c [ExpressionLanguage] added ExpressionFunction and ExpressionFunctionProviderInterface
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants