Search code examples
regexlaravellaravel-4laravel-3

Laravel: Common Regex For route pattern and Model validation


Situation where I came across: Consider the following cases :

  1. Route::pattern() or we can use Route::({method}/{keyword})->where('keyword', {regex});
  2. Validation Rule array( 'keyword' => "/^{regex}$/");

Both accepts different format of regex in case 1: Route::pattern() or in Route::()->where() it does not accept regex in /^{regex}$/ format. It only accepts Route::pattern('keword', {regex}).

in case 2: its accepts regex in /^{regex}$/ pattern.

So in short, I can't apply the same in both place. That is why I have to write two different regex, however they are same.

Am I missing something? Is that possible that model regex and route pattern regex can be defined at once? So changing one regex, we dont have to change another one. Just because of /^$/ ?


Solution

  • Actually you can't do that because in route declaration the regex is simplified, it just accepts a pattern string and it should not contain ^$ because when the route is being compiled by Symfony\Component\Routing\Route class; it just removes the ^ and $ from that string and if you provide slashes /.../ then the route won't work. So, you can't use a regular expression like /^[...]$/ in route declaration. In the Symfony\Component\Routing\Route class you may find a method like this (which prepares the route's regex):

    private function sanitizeRequirement($key, $regex)
    {
        if (!is_string($regex)) {
            throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key));
        }
    
        if ('' !== $regex && '^' === $regex[0]) {
            $regex = (string) substr($regex, 1); // returns false for a single character
        }
    
        if ('$' === substr($regex, -1)) {
            $regex = substr($regex, 0, -1);
        }
    
        if ('' === $regex) {
            throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
        }
    
       // ...
    
        return $regex;
    }
    

    On the other hand, the Validator expects a valid regular expression and you need to specify one like /^[...]$/. So, that's not possible to use same regex for Route and Validator because they are different things and works differently.

    Even if both were same then there is no built-in way to get the route regex pattern in the Validator to apply as a rule. Keep it simple, use those the way they work and don't make it too complicated.