Skip to content

Commit a1141c0

Browse files
committed
feature #19485 [FrameworkBundle] Introduce a cache warmer for Validator based on PhpArrayAdapter (tgalopin)
This PR was merged into the 3.2-dev branch. Discussion ---------- [FrameworkBundle] Introduce a cache warmer for Validator based on PhpArrayAdapter | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | - | Fixed tickets | - | License | MIT | Doc PR | - Following the cache warmer for annotations PR (symfony/symfony#18533), this PR introduces a cache warmer for YAML and XML Validator configuration. Based on the PhpArrayAdapter, it uses the naming conventions (`Resources/config/validation`) to find the files and compile them into a single PHP file stored in the cache directory. This file uses shared memory on PHP 7. The benefit of this PR are the same than the ones of the annotations PR: - validation configuration can be warmed up offline - on PHP 7, there is no need for user extension to get maximum performances (ie. if you use this PR and the other one, you probably won't need to enable APCu to have great performances) - on PHP 7 again, we are not sensitive to APCu memory fragmentation - last but not least, global performance is slightly better (I get 30us per class gain in Blackfire) This PR also deprecates the framework.validator.cache key in favor of the cache pool introduced in symfony/symfony#18544. Commits ------- 6bdaf0b [FrameworkBundle] Introduce a cache warmer for Validator based on PhpArrayAdapter
2 parents c6f3a84 + 8af769d commit a1141c0

File tree

3 files changed

+97
-61
lines changed

3 files changed

+97
-61
lines changed

Mapping/Loader/XmlFileLoader.php

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,7 @@ class XmlFileLoader extends FileLoader
3535
public function loadClassMetadata(ClassMetadata $metadata)
3636
{
3737
if (null === $this->classes) {
38-
// This method may throw an exception. Do not modify the class'
39-
// state before it completes
40-
$xml = $this->parseFile($this->file);
41-
42-
$this->classes = array();
43-
44-
foreach ($xml->namespace as $namespace) {
45-
$this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
46-
}
47-
48-
foreach ($xml->class as $class) {
49-
$this->classes[(string) $class['name']] = $class;
50-
}
38+
$this->loadClassesFromXml();
5139
}
5240

5341
if (isset($this->classes[$metadata->getClassName()])) {
@@ -61,6 +49,20 @@ public function loadClassMetadata(ClassMetadata $metadata)
6149
return false;
6250
}
6351

52+
/**
53+
* Return the names of the classes mapped in this file.
54+
*
55+
* @return string[] The classes names
56+
*/
57+
public function getMappedClasses()
58+
{
59+
if (null === $this->classes) {
60+
$this->loadClassesFromXml();
61+
}
62+
63+
return array_keys($this->classes);
64+
}
65+
6466
/**
6567
* Parses a collection of "constraint" XML nodes.
6668
*
@@ -182,6 +184,23 @@ protected function parseFile($path)
182184
return simplexml_import_dom($dom);
183185
}
184186

187+
private function loadClassesFromXml()
188+
{
189+
// This method may throw an exception. Do not modify the class'
190+
// state before it completes
191+
$xml = $this->parseFile($this->file);
192+
193+
$this->classes = array();
194+
195+
foreach ($xml->namespace as $namespace) {
196+
$this->addNamespaceAlias((string) $namespace['prefix'], trim((string) $namespace));
197+
}
198+
199+
foreach ($xml->class as $class) {
200+
$this->classes[(string) $class['name']] = $class;
201+
}
202+
}
203+
185204
private function loadClassMetadataFromXml(ClassMetadata $metadata, \SimpleXMLElement $classDescription)
186205
{
187206
if (count($classDescription->{'group-sequence-provider'}) > 0) {

Mapping/Loader/YamlFileLoader.php

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,7 @@ class YamlFileLoader extends FileLoader
4242
public function loadClassMetadata(ClassMetadata $metadata)
4343
{
4444
if (null === $this->classes) {
45-
if (null === $this->yamlParser) {
46-
$this->yamlParser = new YamlParser();
47-
}
48-
49-
// This method may throw an exception. Do not modify the class'
50-
// state before it completes
51-
if (false === ($classes = $this->parseFile($this->file))) {
52-
return false;
53-
}
54-
55-
$this->classes = $classes;
56-
57-
if (isset($this->classes['namespaces'])) {
58-
foreach ($this->classes['namespaces'] as $alias => $namespace) {
59-
$this->addNamespaceAlias($alias, $namespace);
60-
}
61-
62-
unset($this->classes['namespaces']);
63-
}
45+
$this->loadClassesFromYaml();
6446
}
6547

6648
if (isset($this->classes[$metadata->getClassName()])) {
@@ -74,6 +56,20 @@ public function loadClassMetadata(ClassMetadata $metadata)
7456
return false;
7557
}
7658

59+
/**
60+
* Return the names of the classes mapped in this file.
61+
*
62+
* @return string[] The classes names
63+
*/
64+
public function getMappedClasses()
65+
{
66+
if (null === $this->classes) {
67+
$this->loadClassesFromYaml();
68+
}
69+
70+
return array_keys($this->classes);
71+
}
72+
7773
/**
7874
* Parses a collection of YAML nodes.
7975
*
@@ -137,12 +133,29 @@ private function parseFile($path)
137133
return $classes;
138134
}
139135

140-
/**
141-
* Loads the validation metadata from the given YAML class description.
142-
*
143-
* @param ClassMetadata $metadata The metadata to load
144-
* @param array $classDescription The YAML class description
145-
*/
136+
private function loadClassesFromYaml()
137+
{
138+
if (null === $this->yamlParser) {
139+
$this->yamlParser = new YamlParser();
140+
}
141+
142+
// This method may throw an exception. Do not modify the class'
143+
// state before it completes
144+
if (false === ($classes = $this->parseFile($this->file))) {
145+
return;
146+
}
147+
148+
$this->classes = $classes;
149+
150+
if (isset($this->classes['namespaces'])) {
151+
foreach ($this->classes['namespaces'] as $alias => $namespace) {
152+
$this->addNamespaceAlias($alias, $namespace);
153+
}
154+
155+
unset($this->classes['namespaces']);
156+
}
157+
}
158+
146159
private function loadClassMetadataFromYaml(ClassMetadata $metadata, array $classDescription)
147160
{
148161
if (isset($classDescription['group_sequence_provider'])) {

ValidatorBuilder.php

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@
2424
use Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface;
2525
use Symfony\Component\Validator\Mapping\Loader\AnnotationLoader;
2626
use Symfony\Component\Validator\Mapping\Loader\LoaderChain;
27+
use Symfony\Component\Validator\Mapping\Loader\LoaderInterface;
2728
use Symfony\Component\Validator\Mapping\Loader\StaticMethodLoader;
2829
use Symfony\Component\Validator\Mapping\Loader\XmlFileLoader;
29-
use Symfony\Component\Validator\Mapping\Loader\XmlFilesLoader;
3030
use Symfony\Component\Validator\Mapping\Loader\YamlFileLoader;
31-
use Symfony\Component\Validator\Mapping\Loader\YamlFilesLoader;
3231
use Symfony\Component\Validator\Validator\RecursiveValidator;
3332

3433
/**
@@ -283,35 +282,40 @@ public function setTranslationDomain($translationDomain)
283282
}
284283

285284
/**
286-
* {@inheritdoc}
285+
* @return LoaderInterface[]
287286
*/
288-
public function getValidator()
287+
public function getLoaders()
289288
{
290-
$metadataFactory = $this->metadataFactory;
289+
$loaders = array();
291290

292-
if (!$metadataFactory) {
293-
$loaders = array();
291+
foreach ($this->xmlMappings as $xmlMapping) {
292+
$loaders[] = new XmlFileLoader($xmlMapping);
293+
}
294294

295-
if (count($this->xmlMappings) > 1) {
296-
$loaders[] = new XmlFilesLoader($this->xmlMappings);
297-
} elseif (1 === count($this->xmlMappings)) {
298-
$loaders[] = new XmlFileLoader($this->xmlMappings[0]);
299-
}
295+
foreach ($this->yamlMappings as $yamlMappings) {
296+
$loaders[] = new YamlFileLoader($yamlMappings);
297+
}
300298

301-
if (count($this->yamlMappings) > 1) {
302-
$loaders[] = new YamlFilesLoader($this->yamlMappings);
303-
} elseif (1 === count($this->yamlMappings)) {
304-
$loaders[] = new YamlFileLoader($this->yamlMappings[0]);
305-
}
299+
foreach ($this->methodMappings as $methodName) {
300+
$loaders[] = new StaticMethodLoader($methodName);
301+
}
306302

307-
foreach ($this->methodMappings as $methodName) {
308-
$loaders[] = new StaticMethodLoader($methodName);
309-
}
303+
if ($this->annotationReader) {
304+
$loaders[] = new AnnotationLoader($this->annotationReader);
305+
}
310306

311-
if ($this->annotationReader) {
312-
$loaders[] = new AnnotationLoader($this->annotationReader);
313-
}
307+
return $loaders;
308+
}
309+
310+
/**
311+
* {@inheritdoc}
312+
*/
313+
public function getValidator()
314+
{
315+
$metadataFactory = $this->metadataFactory;
314316

317+
if (!$metadataFactory) {
318+
$loaders = $this->getLoaders();
315319
$loader = null;
316320

317321
if (count($loaders) > 1) {

0 commit comments

Comments
 (0)