Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0bede19

Browse filesBrowse files
committed
minor #2344 [TwigComponent] Improve ComponentFactory performances (smnandre)
This PR was squashed before being merged into the 2.x branch. Discussion ---------- [TwigComponent] Improve ComponentFactory performances ComponentFactory Quick Optimization Minor change with.. mid impact (on large number of renders) Commits ------- 6486933ca [TwigComponent] Improve ComponentFactory performances
2 parents ca96b64 + db99014 commit 0bede19
Copy full SHA for 0bede19

File tree

Expand file treeCollapse file tree

3 files changed

+39
-26
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+39
-26
lines changed

‎src/ComponentFactory.php

Copy file name to clipboardExpand all lines: src/ComponentFactory.php
+37-25Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Psr\EventDispatcher\EventDispatcherInterface;
1515
use Symfony\Component\DependencyInjection\ServiceLocator;
1616
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
17+
use Symfony\Contracts\Service\ResetInterface;
1718
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
1819
use Symfony\UX\TwigComponent\Event\PostMountEvent;
1920
use Symfony\UX\TwigComponent\Event\PreMountEvent;
@@ -23,8 +24,12 @@
2324
*
2425
* @internal
2526
*/
26-
final class ComponentFactory
27+
final class ComponentFactory implements ResetInterface
2728
{
29+
private static $mountMethods = [];
30+
private static $preMountMethods = [];
31+
private static $postMountMethods = [];
32+
2833
/**
2934
* @param array<string, array> $config
3035
* @param array<class-string, string> $classMap
@@ -141,37 +146,40 @@ public function get(string $name): object
141146

142147
private function mount(object $component, array &$data): void
143148
{
144-
try {
145-
$method = (new \ReflectionClass($component))->getMethod('mount');
146-
} catch (\ReflectionException) {
147-
// no hydrate method
148-
return;
149-
}
150-
151149
if ($component instanceof AnonymousComponent) {
152150
$component->mount($data);
153151

154152
return;
155153
}
156154

157-
$parameters = [];
155+
if (null === (self::$mountMethods[$component::class] ?? null)) {
156+
try {
157+
$mountMethod = self::$mountMethods[$component::class] = (new \ReflectionClass($component))->getMethod('mount');
158+
} catch (\ReflectionException) {
159+
self::$mountMethods[$component::class] = false;
158160

159-
foreach ($method->getParameters() as $refParameter) {
160-
$name = $refParameter->getName();
161+
return;
162+
}
163+
}
161164

162-
if (\array_key_exists($name, $data)) {
163-
$parameters[] = $data[$name];
165+
if (false === $mountMethod ??= self::$mountMethods[$component::class]) {
166+
return;
167+
}
164168

169+
$parameters = [];
170+
foreach ($mountMethod->getParameters() as $refParameter) {
171+
if (\array_key_exists($name = $refParameter->getName(), $data)) {
172+
$parameters[] = $data[$name];
165173
// remove the data element so it isn't used to set the property directly.
166174
unset($data[$name]);
167175
} elseif ($refParameter->isDefaultValueAvailable()) {
168176
$parameters[] = $refParameter->getDefaultValue();
169177
} else {
170-
throw new \LogicException(\sprintf('%s::mount() has a required $%s parameter. Make sure this is passed or make give a default value.', $component::class, $refParameter->getName()));
178+
throw new \LogicException(\sprintf('%s::mount() has a required $%s parameter. Make sure to pass it or give it a default value.', $component::class, $name));
171179
}
172180
}
173181

174-
$component->mount(...$parameters);
182+
$mountMethod->invoke($component, ...$parameters);
175183
}
176184

177185
private function preMount(object $component, array $data, ComponentMetadata $componentMetadata): array
@@ -180,10 +188,9 @@ private function preMount(object $component, array $data, ComponentMetadata $com
180188
$this->eventDispatcher->dispatch($event);
181189
$data = $event->getData();
182190

183-
foreach (AsTwigComponent::preMountMethods($component) as $method) {
184-
$newData = $component->{$method->name}($data);
185-
186-
if (null !== $newData) {
191+
$methods = self::$preMountMethods[$component::class] ??= AsTwigComponent::preMountMethods($component::class);
192+
foreach ($methods as $method) {
193+
if (null !== $newData = $method->invoke($component, $data)) {
187194
$data = $newData;
188195
}
189196
}
@@ -199,19 +206,17 @@ private function postMount(object $component, array $data, ComponentMetadata $co
199206
$event = new PostMountEvent($component, $data, $componentMetadata);
200207
$this->eventDispatcher->dispatch($event);
201208
$data = $event->getData();
202-
$extraMetadata = $event->getExtraMetadata();
203209

204-
foreach (AsTwigComponent::postMountMethods($component) as $method) {
205-
$newData = $component->{$method->name}($data);
206-
207-
if (null !== $newData) {
210+
$methods = self::$postMountMethods[$component::class] ??= AsTwigComponent::postMountMethods($component::class);
211+
foreach ($methods as $method) {
212+
if (null !== $newData = $method->invoke($component, $data)) {
208213
$data = $newData;
209214
}
210215
}
211216

212217
return [
213218
'data' => $data,
214-
'extraMetadata' => $extraMetadata,
219+
'extraMetadata' => $event->getExtraMetadata(),
215220
];
216221
}
217222

@@ -248,4 +253,11 @@ private function throwUnknownComponentException(string $name): void
248253

249254
throw new \InvalidArgumentException($message);
250255
}
256+
257+
public function reset(): void
258+
{
259+
self::$mountMethods = [];
260+
self::$preMountMethods = [];
261+
self::$postMountMethods = [];
262+
}
251263
}

‎src/DependencyInjection/TwigComponentExtension.php

Copy file name to clipboardExpand all lines: src/DependencyInjection/TwigComponentExtension.php
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static function (ChildDefinition $definition, AsTwigComponent $attribute) {
9292
new Reference('event_dispatcher'),
9393
new AbstractArgument(\sprintf('Added in %s.', TwigComponentPass::class)),
9494
])
95+
->addTag('kernel.reset', ['method' => 'reset'])
9596
;
9697

9798
$container->register('ux.twig_component.component_stack', ComponentStack::class);

‎tests/Integration/ComponentFactoryTest.php

Copy file name to clipboardExpand all lines: tests/Integration/ComponentFactoryTest.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function testMountCanHaveOptionalParameters(): void
8787
public function testExceptionThrownIfRequiredMountParameterIsMissingFromPassedData(): void
8888
{
8989
$this->expectException(\LogicException::class);
90-
$this->expectExceptionMessage('Symfony\UX\TwigComponent\Tests\Fixtures\Component\ComponentC::mount() has a required $propA parameter. Make sure this is passed or make give a default value.');
90+
$this->expectExceptionMessage('Symfony\UX\TwigComponent\Tests\Fixtures\Component\ComponentC::mount() has a required $propA parameter. Make sure to pass it or give it a default value.');
9191

9292
$this->createComponent('component_c');
9393
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.