19 Feb 2018

feedSymfony Blog

New in Symfony 4.1: Validator improvements

Deprecated the checkDNS option of the URL validator

Roland Franssen

Contributed by
Roland Franssen
in #25516.

In Symfony 4.1, the checkDNS option (and its related dnsMessage option) of the Url constraint has been deprecated. This option allowed to check whether the host associated with the given URL existed. It used the checkdnsrr() PHP function and it's been deprecated (and removed in Symfony 5.0) because its results are not fully reliable.

No alternative is provided, so if you still want to apply this validation, create a custom validation and use the checkdnsrr() PHP function.

Allow to pass custom values to Expression validator

Gabriel Ostrolucký

Contributed by
Gabriel Ostrolucký
in #25504.

In Symfony 4.1, the Expression constraint accepts a new option called values to pass arbitrary values and use them in your expressions:

1
2
3
4
5
6
7
8
use Symfony\Component\Validator\Constraints\Expression;

$constraint = new Expression([
    'expression' => 'value + custom == 2',
    'values' => [
        'custom' => 1,
    ],
]);

Added a canonicalize option to the Locale validator

Javier Spagnoletti

Contributed by
Javier Spagnoletti
in #22353.

In Symfony 4.1, the Locale constraint defines a new boolean option called canonicalize. If true, the given locale value is transformed into its canonical form before validating it.

For example, FR-fr.utf8 is transformed into fr_FR, UZ-cYRL-uz is transformed into uz_Cyrl_UZ, etc.

1
2
3
4
5
6
7
use Symfony\Component\Validator\Constraints as Assert;

class User
{
    /** @Assert\Locale(canonicalize = true) */
     protected $locale;
}

Added support for validating URLs without protocol

Peter Smeets

Contributed by
Peter Smeets
in #24308.

The Url constraint defines the protocols option to configure the protocols allowed for the URLs (['http', 'https'] by default). In Symfony 4.1 we added a new boolean option called relativeProtocol. If true, URLs without protocol (e.g. //example.com) are considered valid too:

1
2
3
4
5
6
7
use Symfony\Component\Validator\Constraints as Assert;

class Author
{
    /** @Assert\Url(relativeProtocol = true) */
     protected $bioUrl;
}

Be trained by Symfony experts - 2018-02-26 Clichy - 2018-02-26 Clichy - 2018-02-28 Clichy

19 Feb 2018 9:19am GMT

18 Feb 2018

feedSymfony Blog

A week of symfony #581 (12-18 February 2018)

This week Symfony added support for reproducible builds. In addition, it finished the feature to make Symfony's router the fastest PHP router and it also improved the dependency injection container performance.

Symfony development highlights

2.7 changelog:

3.4 changelog:

Master changelog:

Newest issues and pull requests

They talked about us


Be trained by Symfony experts - 2018-02-26 Clichy - 2018-02-26 Clichy - 2018-02-28 Clichy

18 Feb 2018 9:07am GMT

15 Feb 2018

feedSymfony Blog

New in Symfony 4.1: Fastest PHP Router

Nicolas Grekas

Contributed by
Nicolas Grekas
in #26059 and #26169.

Symfony 4 is the fastest PHP framework according to independent benchmarks, but we are continuously working on making it faster. In Symfony 4.1, we improved the Routing component to make it much faster when matching incoming URLs.

In web applications, routing is divided in two main operations: generation, which generates a URL from the given route and parameters; and matching, which decides which PHP code (i.e. controller) is executed as the response of an incoming URL.

In order to speed up the application, during the compilation phase Symfony generates a PHP class called "matcher" which contains all the route definitions optimized to match incoming URLs. For example, this is a snippet of the class generated for the Symfony Demo application:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// var/cache/prod/srcProdDebugProjectContainerUrlMatcher.php
class srcProdDebugProjectContainerUrlMatcher
{
    // ...

    public function match($rawPathinfo)
    {
        // ...

        // blog_post
        if (preg_match('#^/(?P<_locale>en|fr|de|es)/blog/posts/(?P<slug>[^/]++)$#s', $pathinfo, $matches)) {
            if ('GET' !== $canonicalMethod) {
                $allow[] = 'GET';
                goto not_blog_post;
            }

            return $this->mergeDefaults(array_replace($matches, array('_route' => 'blog_post')), array (  '_controller' => 'App\\Controller\\BlogController::postShow',  '_locale' => 'en',));
        }
        not_blog_post:

        // ...
    }
}

In Symfony 4.1 we refactored the matcher class generator based on the ideas shared in the following article: Fast request routing using regular expressions. The article explains the technique used by FastRoute, a routing library created by the genius PHP contributor Nikita Popov.

The basic idea is to avoid making separate preg_match() calls for each route and instead, combine all regular expressions into a single regular expression. We also made many other big and small optimizations. If you are curious, see the Pull Request #26059 and #26169 for all the details.

All in all, using the same Symfony Demo application example, this is how the blog_post route is matched now:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$regexList = array(
    0 => '{^(?'
            .'|/(en|fr|de|es)/admin/post/?(*:82)'
            .'|/(en|fr|de|es)/admin/post/new(*:166)'
            .'|/(en|fr|de|es)/admin/post/(\\d+)(*:253)'
            .'|/(en|fr|de|es)/admin/post/(\\d+)/edit(*:345)'
            .'|/(en|fr|de|es)/admin/post/([^/]++)/delete(*:442)'
            .'|/(en|fr|de|es)/blog/?(*:519)'
            .'|/(en|fr|de|es)/blog/rss\\.xml(*:603)'
            .'|/(en|fr|de|es)/blog/page/([1-9]\\d*)(*:694)'
            .'|/(en|fr|de|es)/blog/posts/([^/]++)(*:784)'
            .'|/(en|fr|de|es)/blog/comment/([^/]++)/new(*:880)'
            .'|/(en|fr|de|es)/blog/search(*:962)'
            .'|/(en|fr|de|es)/login(*:1038)'
            .'|/(en|fr|de|es)/logout(*:1116)'
            .'|/(en|fr|de|es)?(*:1188)'
        .')$}sD',
);

foreach ($regexList as $offset => $regex) {
    // ...

    default:
        $routes = array(
            // ...
            784 => array(array('_route' => 'blog_post', '_controller' => 'App\\Controller\\BlogController::postShow', '_locale' => 'en'), array('_locale', 'slug'), array('GET' => 0), null),
        );

    // ...
}

In practice, combining all regular expressions improves URL matching performance by almost two orders of magnitude. In our benchmarks, Symfony 4.1 URL matching is 77 times faster than in previous Symfony versions. This also means that Symfony 4.1 router is now the fastest PHP router, beating FastRoute and all the other routing libraries.

Best of all: you don't need to make any change in your application to use this fast router. You just need to upgrade to Symfony 4.1 when it's released at the end of May 2018. Meanwhile you can test it in your applications and report any issue that you find.

Update: Nicolas has published two technical articles explaining in detail how the new router works:


Be trained by Symfony experts - 2018-02-26 Clichy - 2018-02-26 Clichy - 2018-02-28 Clichy

15 Feb 2018 3:34pm GMT