bug #12329 [Routing] serialize the compiled route to speed things up (Tobion)
This PR was merged into the 2.3 branch.
Discussion
----------
[Routing] serialize the compiled route to speed things up
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | not really
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | #12012, #12220
| License | MIT
| Doc PR | -
This also makes the CompiledRoute implement Serializable in order to:
1. make the serialization format shorter
2. have no null bytes in there, which the native serializer add for private properties, and thus would complicate saving in databases etc.
3. Since the Route now includes the CompiledRoute in the serialization, the CompiledRoute serialization must be consistent as well. We can only ensure that in future symfony version by implementing Serializable.
We should add to our symfony BC promise, that only classes that implement Serializable are ensured to be deserializable correctly with serialized representations of the class in previous symfony versions.
Commits
-------
fd88de7
[Routing] serialize the compiled route to speed things up
This commit is contained in:
commit
9a8ac524df
@ -16,7 +16,7 @@ namespace Symfony\Component\Routing;
|
|||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*/
|
*/
|
||||||
class CompiledRoute
|
class CompiledRoute implements \Serializable
|
||||||
{
|
{
|
||||||
private $variables;
|
private $variables;
|
||||||
private $tokens;
|
private $tokens;
|
||||||
@ -51,6 +51,39 @@ class CompiledRoute
|
|||||||
$this->variables = $variables;
|
$this->variables = $variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function serialize()
|
||||||
|
{
|
||||||
|
return serialize(array(
|
||||||
|
'vars' => $this->variables,
|
||||||
|
'path_prefix' => $this->staticPrefix,
|
||||||
|
'path_regex' => $this->regex,
|
||||||
|
'path_tokens' => $this->tokens,
|
||||||
|
'path_vars' => $this->pathVariables,
|
||||||
|
'host_regex' => $this->hostRegex,
|
||||||
|
'host_tokens' => $this->hostTokens,
|
||||||
|
'host_vars' => $this->hostVariables,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function unserialize($serialized)
|
||||||
|
{
|
||||||
|
$data = unserialize($serialized);
|
||||||
|
$this->variables = $data['vars'];
|
||||||
|
$this->staticPrefix = $data['path_prefix'];
|
||||||
|
$this->regex = $data['path_regex'];
|
||||||
|
$this->tokens = $data['path_tokens'];
|
||||||
|
$this->pathVariables = $data['path_vars'];
|
||||||
|
$this->hostRegex = $data['host_regex'];
|
||||||
|
$this->hostTokens = $data['host_tokens'];
|
||||||
|
$this->hostVariables = $data['host_vars'];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the static prefix.
|
* Returns the static prefix.
|
||||||
*
|
*
|
||||||
|
@ -95,6 +95,9 @@ class Route implements \Serializable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
public function serialize()
|
public function serialize()
|
||||||
{
|
{
|
||||||
return serialize(array(
|
return serialize(array(
|
||||||
@ -105,12 +108,16 @@ class Route implements \Serializable
|
|||||||
'options' => $this->options,
|
'options' => $this->options,
|
||||||
'schemes' => $this->schemes,
|
'schemes' => $this->schemes,
|
||||||
'methods' => $this->methods,
|
'methods' => $this->methods,
|
||||||
|
'compiled' => $this->compiled,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unserialize($data)
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function unserialize($serialized)
|
||||||
{
|
{
|
||||||
$data = unserialize($data);
|
$data = unserialize($serialized);
|
||||||
$this->path = $data['path'];
|
$this->path = $data['path'];
|
||||||
$this->host = $data['host'];
|
$this->host = $data['host'];
|
||||||
$this->defaults = $data['defaults'];
|
$this->defaults = $data['defaults'];
|
||||||
@ -118,6 +125,9 @@ class Route implements \Serializable
|
|||||||
$this->options = $data['options'];
|
$this->options = $data['options'];
|
||||||
$this->schemes = $data['schemes'];
|
$this->schemes = $data['schemes'];
|
||||||
$this->methods = $data['methods'];
|
$this->methods = $data['methods'];
|
||||||
|
if (isset($data['compiled'])) {
|
||||||
|
$this->compiled = $data['compiled'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,7 +212,7 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testSerialize()
|
public function testSerialize()
|
||||||
{
|
{
|
||||||
$route = new Route('/{foo}', array('foo' => 'default'), array('foo' => '\d+'));
|
$route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+'));
|
||||||
|
|
||||||
$serialized = serialize($route);
|
$serialized = serialize($route);
|
||||||
$unserialized = unserialize($serialized);
|
$unserialized = unserialize($serialized);
|
||||||
@ -220,4 +220,39 @@ class RouteTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals($route, $unserialized);
|
$this->assertEquals($route, $unserialized);
|
||||||
$this->assertNotSame($route, $unserialized);
|
$this->assertNotSame($route, $unserialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the compiled version is also serialized to prevent the overhead
|
||||||
|
* of compiling it again after unserialize.
|
||||||
|
*/
|
||||||
|
public function testSerializeWhenCompiled()
|
||||||
|
{
|
||||||
|
$route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+'));
|
||||||
|
$route->setHost('{locale}.example.net');
|
||||||
|
$route->compile();
|
||||||
|
|
||||||
|
$serialized = serialize($route);
|
||||||
|
$unserialized = unserialize($serialized);
|
||||||
|
|
||||||
|
$this->assertEquals($route, $unserialized);
|
||||||
|
$this->assertNotSame($route, $unserialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that the serialized representation of a route in one symfony version
|
||||||
|
* also works in later symfony versions, i.e. the unserialized route is in the
|
||||||
|
* same state as another, semantically equivalent, route.
|
||||||
|
*/
|
||||||
|
public function testSerializedRepresentationKeepsWorking()
|
||||||
|
{
|
||||||
|
$serialized = 'C:31:"Symfony\Component\Routing\Route":933:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":568:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:38:"#^(?P<locale>[^\.]++)\.example\.net$#s";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}';
|
||||||
|
$unserialized = unserialize($serialized);
|
||||||
|
|
||||||
|
$route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+'));
|
||||||
|
$route->setHost('{locale}.example.net');
|
||||||
|
$route->compile();
|
||||||
|
|
||||||
|
$this->assertEquals($route, $unserialized);
|
||||||
|
$this->assertNotSame($route, $unserialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user