From 7060f2bb8936990de4ccb00936c56801c9731ddd Mon Sep 17 00:00:00 2001 From: Lonny Kapelushnik Date: Sun, 21 Apr 2024 20:43:27 -0600 Subject: [PATCH 1/5] Blade Component Loop Speed Improvement --- src/Illuminate/View/Factory.php | 48 +++++++++++++++++++++++++++++++-- tests/View/ViewFactoryTest.php | 12 +++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/View/Factory.php b/src/Illuminate/View/Factory.php index 7ca8f94b7a21..8bafc6749d09 100755 --- a/src/Illuminate/View/Factory.php +++ b/src/Illuminate/View/Factory.php @@ -90,6 +90,20 @@ class Factory implements FactoryContract */ protected $renderedOnce = []; + /** + * The name of the engine for a specific path + * + * @var array + */ + protected $pathEngines = []; + + /** + * The normalized names of the views. + * + * @var array + */ + protected $normalizedNames = []; + /** * Create a new view factory instance. * @@ -247,7 +261,14 @@ public function renderEach($view, $data, $iterator, $empty = 'raw|') */ protected function normalizeName($name) { - return ViewName::normalize($name); + if (isset($this->normalizedNames[$name])) { + return $this->normalizedNames[$name]; + } + + + $this->normalizedNames[$name] = ViewName::normalize($name); + + return $this->normalizedNames[$name]; } /** @@ -301,13 +322,19 @@ public function exists($view) */ public function getEngineFromPath($path) { + if ($this->hasPathEngine($path)) { + return $this->pathEngines[$path]; + } + if (! $extension = $this->getExtension($path)) { throw new InvalidArgumentException("Unrecognized extension in file: {$path}."); } $engine = $this->extensions[$extension]; - return $this->engines->resolve($engine); + $this->setPathEngine($path, $this->engines->resolve($engine)); + + return $this->pathEngines[$path]; } /** @@ -467,6 +494,23 @@ public function addExtension($extension, $engine, $resolver = null) unset($this->extensions[$extension]); $this->extensions = array_merge([$extension => $engine], $this->extensions); + + $this->resetPathEngines(); + } + + public function setPathEngine($path, $engine) + { + $this->pathEngines[$path] = $engine; + } + + public function hasPathEngine($path) + { + return isset($this->pathEngines[$path]); + } + + public function resetPathEngines() + { + $this->pathEngines = []; } /** diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php index 5465c78af0b2..bbbf0e555204 100755 --- a/tests/View/ViewFactoryTest.php +++ b/tests/View/ViewFactoryTest.php @@ -1072,6 +1072,18 @@ public function testIncrementingLoopIndicesOfUncountable() $this->assertNull($factory->getLoopStack()[0]['last']); } + public function testPathEngines() + { + $factory = $this->getFactory(); + + $this->assertFalse($factory->hasPathEngine('foo')); + $factory->setPathEngine('foo', 'bar'); + $this->assertTrue($factory->hasPathEngine('foo')); + $this->assertSame('bar', $factory->getPathEngine('foo')); + $factory->resetPathEngines(); + $this->assertFalse($factory->hasPathEngine('foo')); + } + public function testMacro() { $factory = $this->getFactory(); From be862c75d5651f89196a9655fe4ee5f3f841a7e1 Mon Sep 17 00:00:00 2001 From: Lonny Kapelushnik Date: Sun, 21 Apr 2024 21:47:40 -0600 Subject: [PATCH 2/5] Corrected tests --- src/Illuminate/View/Factory.php | 9 +++++++-- tests/View/ViewFactoryTest.php | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/View/Factory.php b/src/Illuminate/View/Factory.php index 8bafc6749d09..d2973b2e45e3 100755 --- a/src/Illuminate/View/Factory.php +++ b/src/Illuminate/View/Factory.php @@ -323,7 +323,7 @@ public function exists($view) public function getEngineFromPath($path) { if ($this->hasPathEngine($path)) { - return $this->pathEngines[$path]; + return $this->getPathEngine($path); } if (! $extension = $this->getExtension($path)) { @@ -334,7 +334,7 @@ public function getEngineFromPath($path) $this->setPathEngine($path, $this->engines->resolve($engine)); - return $this->pathEngines[$path]; + return $this->getPathEngine($path); } /** @@ -503,6 +503,11 @@ public function setPathEngine($path, $engine) $this->pathEngines[$path] = $engine; } + public function getPathEngine($path) + { + return $this->pathEngines[$path]; + } + public function hasPathEngine($path) { return isset($this->pathEngines[$path]); diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php index bbbf0e555204..cbb74405fd9c 100755 --- a/tests/View/ViewFactoryTest.php +++ b/tests/View/ViewFactoryTest.php @@ -842,7 +842,7 @@ public function testMakeWithSlashAndDot() { $factory = $this->getFactory(); $factory->getFinder()->shouldReceive('find')->twice()->with('foo.bar')->andReturn('path.php'); - $factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class)); + $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('php')->andReturn(m::mock(Engine::class)); $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false); $factory->make('foo/bar'); $factory->make('foo.bar'); @@ -852,7 +852,7 @@ public function testNamespacedViewNamesAreNormalizedProperly() { $factory = $this->getFactory(); $factory->getFinder()->shouldReceive('find')->twice()->with('vendor/package::foo.bar')->andReturn('path.php'); - $factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class)); + $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('php')->andReturn(m::mock(Engine::class)); $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false); $factory->make('vendor/package::foo/bar'); $factory->make('vendor/package::foo.bar'); From 7da01822c7d1490d8411dae7903e9da25fccc5cd Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 22 Apr 2024 14:34:07 -0500 Subject: [PATCH 3/5] formatting --- src/Illuminate/View/Factory.php | 51 +++++++-------------------------- 1 file changed, 11 insertions(+), 40 deletions(-) diff --git a/src/Illuminate/View/Factory.php b/src/Illuminate/View/Factory.php index d2973b2e45e3..f6ec7f7db079 100755 --- a/src/Illuminate/View/Factory.php +++ b/src/Illuminate/View/Factory.php @@ -91,18 +91,18 @@ class Factory implements FactoryContract protected $renderedOnce = []; /** - * The name of the engine for a specific path + * The cached array of engines for paths. * * @var array */ - protected $pathEngines = []; + protected $pathEngineCache = []; /** - * The normalized names of the views. + * The cache of normalized names for views. * * @var array */ - protected $normalizedNames = []; + protected $normalizedNameCache = []; /** * Create a new view factory instance. @@ -261,14 +261,7 @@ public function renderEach($view, $data, $iterator, $empty = 'raw|') */ protected function normalizeName($name) { - if (isset($this->normalizedNames[$name])) { - return $this->normalizedNames[$name]; - } - - - $this->normalizedNames[$name] = ViewName::normalize($name); - - return $this->normalizedNames[$name]; + return $this->normalizedNames[$name] ??= ViewName::normalize($name); } /** @@ -322,19 +315,17 @@ public function exists($view) */ public function getEngineFromPath($path) { - if ($this->hasPathEngine($path)) { - return $this->getPathEngine($path); + if (isset($this->pathEngineCache[$path])) { + return $this->engines->resolve($this->pathEngineCache[$path]); } if (! $extension = $this->getExtension($path)) { throw new InvalidArgumentException("Unrecognized extension in file: {$path}."); } - $engine = $this->extensions[$extension]; - - $this->setPathEngine($path, $this->engines->resolve($engine)); - - return $this->getPathEngine($path); + return $this->engines->resolve( + $this->pathEngineCache[$path] = $this->extensions[$extension] + ); } /** @@ -495,27 +486,7 @@ public function addExtension($extension, $engine, $resolver = null) $this->extensions = array_merge([$extension => $engine], $this->extensions); - $this->resetPathEngines(); - } - - public function setPathEngine($path, $engine) - { - $this->pathEngines[$path] = $engine; - } - - public function getPathEngine($path) - { - return $this->pathEngines[$path]; - } - - public function hasPathEngine($path) - { - return isset($this->pathEngines[$path]); - } - - public function resetPathEngines() - { - $this->pathEngines = []; + $this->pathEngineCache = []; } /** From 16c35de58e34a618a9dffc1c0f3e71f032d873ad Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Mon, 22 Apr 2024 14:34:59 -0500 Subject: [PATCH 4/5] remove test --- tests/View/ViewFactoryTest.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php index cbb74405fd9c..aeef531d6af1 100755 --- a/tests/View/ViewFactoryTest.php +++ b/tests/View/ViewFactoryTest.php @@ -1072,18 +1072,6 @@ public function testIncrementingLoopIndicesOfUncountable() $this->assertNull($factory->getLoopStack()[0]['last']); } - public function testPathEngines() - { - $factory = $this->getFactory(); - - $this->assertFalse($factory->hasPathEngine('foo')); - $factory->setPathEngine('foo', 'bar'); - $this->assertTrue($factory->hasPathEngine('foo')); - $this->assertSame('bar', $factory->getPathEngine('foo')); - $factory->resetPathEngines(); - $this->assertFalse($factory->hasPathEngine('foo')); - } - public function testMacro() { $factory = $this->getFactory(); From e08661d8b794f09c40d41db58d0906db1f3ba99b Mon Sep 17 00:00:00 2001 From: Lonny Kapelushnik Date: Mon, 22 Apr 2024 14:52:18 -0600 Subject: [PATCH 5/5] Updated tests --- tests/View/ViewFactoryTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/View/ViewFactoryTest.php b/tests/View/ViewFactoryTest.php index aeef531d6af1..5465c78af0b2 100755 --- a/tests/View/ViewFactoryTest.php +++ b/tests/View/ViewFactoryTest.php @@ -842,7 +842,7 @@ public function testMakeWithSlashAndDot() { $factory = $this->getFactory(); $factory->getFinder()->shouldReceive('find')->twice()->with('foo.bar')->andReturn('path.php'); - $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('php')->andReturn(m::mock(Engine::class)); + $factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class)); $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false); $factory->make('foo/bar'); $factory->make('foo.bar'); @@ -852,7 +852,7 @@ public function testNamespacedViewNamesAreNormalizedProperly() { $factory = $this->getFactory(); $factory->getFinder()->shouldReceive('find')->twice()->with('vendor/package::foo.bar')->andReturn('path.php'); - $factory->getEngineResolver()->shouldReceive('resolve')->once()->with('php')->andReturn(m::mock(Engine::class)); + $factory->getEngineResolver()->shouldReceive('resolve')->twice()->with('php')->andReturn(m::mock(Engine::class)); $factory->getDispatcher()->shouldReceive('hasListeners')->andReturn(false); $factory->make('vendor/package::foo/bar'); $factory->make('vendor/package::foo.bar');