Skip to content

Instantly share code, notes, and snippets.

@fabpot
Last active December 22, 2015 06:48
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabpot/6433461 to your computer and use it in GitHub Desktop.
Save fabpot/6433461 to your computer and use it in GitHub Desktop.
<?php
require_once __DIR__.'/autoload.php.dist';
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
// This condition should be true for the route to match
$condition = "method in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'";
$routes = new RouteCollection();
// here, I'm adding the condition as a Route option
$routes->add('hello', new Route('/hello/{name}', array(), array(), array('condition' => $condition)));
class RequestUrlMatcher extends UrlMatcher implements RequestMatcherInterface
{
private $language;
public function setExpressionLanguage(ExpressionLanguage $language)
{
$this->language = $language;
}
public function matchRequest(Request $request)
{
$this->request = $request;
return $this->match($request->getPathInfo());
}
protected function handleRouteRequirements($pathinfo, $name, Route $route)
{
$options = $route->getOptions();
$status = self::REQUIREMENT_MISMATCH;
if (!isset($options['condition'])) {
$status = self::REQUIREMENT_MATCH;
} else {
// the variables that can be accessed in the condition expression
$context = array(
'method' => $this->context->getMethod(),
'request' => $this->request,
);
// the route matches only if the condition evaluates to true
if ($this->language->evaluate($options['condition'], $context)) {
$status = self::REQUIREMENT_MATCH;
}
}
return array($status, null);
}
}
$context = new RequestContext();
$request = Request::create('/hello/Fabien', 'GET', array(), array(), array(), array('HTTP_USER_AGENT' => 'Firefox/1.0'));
$context->fromRequest($request);
$matcher = new RequestUrlMatcher($routes, $context);
$matcher->setExpressionLanguage(new ExpressionLanguage());
// this is going to match as the method is GET and the browser contains Firefox
var_export($matcher->matchRequest($request));
# corresponding YAML configuration file for the code above
hello:
path: /hello/{name}
options:
condition: "method in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'"
# what we could do if condition would become a first class citizen in Symfony
hello:
path: /hello/{name}
condition: "method in ['GET', 'HEAD'] and request.headers.get('User-Agent') =~ '/firefox/i'"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment