@@ -44,8 +44,12 @@ trait ViewTrait
4444 private array $ fallbackExtensions = [self ::PHP_EXTENSION ];
4545
4646 /**
47- * @var array A list of available renderers indexed by their corresponding
48- * supported file extensions.
47+ * @var array A list of available renderers indexed by their corresponding supported file extensions.
48+ *
49+ * The renderers are stored in descending order by extension length (longest first).
50+ * This ensures that more specific extensions (e.g., "blade.php") are matched before
51+ * shorter ones (e.g., "php").
52+ *
4953 * @psalm-var array<string, TemplateRendererInterface>
5054 */
5155 private array $ renderers = [];
@@ -122,6 +126,11 @@ public function withRenderers(array $renderers): static
122126 }
123127 }
124128
129+ uksort (
130+ $ renderers ,
131+ static fn (string $ a , string $ b ): int => strlen ($ b ) <=> strlen ($ a )
132+ );
133+
125134 $ new = clone $ this ;
126135 $ new ->renderers = $ renderers ;
127136 return $ new ;
@@ -477,9 +486,7 @@ public function render(string $view, array $parameters = []): string
477486 ];
478487
479488 if ($ this ->beforeRender ($ viewFile , $ parameters )) {
480- $ ext = pathinfo ($ viewFile , PATHINFO_EXTENSION );
481- $ renderer = $ this ->renderers [$ ext ] ?? new PhpTemplateRenderer ();
482- $ output = $ renderer ->render ($ this , $ viewFile , $ parameters );
489+ $ output = $ this ->getRenderer ($ viewFile )->render ($ this , $ viewFile , $ parameters );
483490 $ output = $ this ->afterRender ($ viewFile , $ parameters , $ output );
484491 }
485492
@@ -568,6 +575,27 @@ abstract protected function createAfterRenderEvent(
568575 string $ result
569576 ): AfterRenderEventInterface ;
570577
578+ /**
579+ * Returns the appropriate template renderer for the given view file.
580+ *
581+ * Selects a renderer based on the view file extension. If no matching renderer is found
582+ * for the file extension, returns a default {@see PhpTemplateRenderer}.
583+ *
584+ * @param string $viewFile The view file path.
585+ *
586+ * @return TemplateRendererInterface The template renderer instance.
587+ */
588+ private function getRenderer (string $ viewFile ): TemplateRendererInterface
589+ {
590+ $ fileName = basename ($ viewFile );
591+ foreach ($ this ->renderers as $ extension => $ renderer ) {
592+ if (str_ends_with ($ fileName , '. ' . $ extension )) {
593+ return $ renderer ;
594+ }
595+ }
596+ return new PhpTemplateRenderer ();
597+ }
598+
571599 /**
572600 * This method is invoked right before {@see render()} renders a view file.
573601 *
0 commit comments