Skip to content

refactor(view)!: improved view component rendering#1980

Draft
brendt wants to merge 29 commits into3.xfrom
view-includes
Draft

refactor(view)!: improved view component rendering#1980
brendt wants to merge 29 commits into3.xfrom
view-includes

Conversation

@brendt
Copy link
Member

@brendt brendt commented Feb 17, 2026

This PR fixes some long-standing issues with tempest/view. Technically it does not introduce any breaking changes, but it might lead to failed template rendering in some occasions. First, an overview of what's changing:

  • Compiled templates will now use PHP's include instead of compiling everything to one file. This fixes Colliding class names in view imports #1380 when two view components import classes with the same names from different namespaces
  • Namespaces can still collide, because they are passed from the parent views or view component to child view components. We provide a clear error in this case
  • We've added source mapping, so that now we can refer to view source files with line number when a view compilation error occurs, fixing Improved lexer context #1194

Breaking changes

With this PR comes a refactor to the Element interface, which now requires a getImports method. However, a default implementation is provided by the IsElement trait, and thus should have no impact.

Apart from that, this PR may still lead to invalid view files with missing imports.

Let's say you have these two components:

// x-a.view.php

<?php 
use App\HomeController::class;
?>

{{ uri(HomeController::class) }}
// x-b.view.php

<?php 
use App\BlogController::class; 
use function Tempest\Router\uri;
?>

{{ uri(HomeController::class) }}

When these two view components were referenced in the same file, they would render fine before this PR:

<x-a />
<x-b />

That's because tempest views used to be compiled into one big file, and all import statements would be grouped together. However, now that we've switched to including compiled view components, the above code would break, since there's no use function Tempest\Router\uri; within the scope of <x-a>

The fix is to include uri in <x-a> as well:

// x-a.view.php

<?php 
use App\HomeController::class;
use function Tempest\Router\uri;
?>

{{ uri(HomeController::class) }}

Thanks to source-mapping, you will now get a clear exception pointing you to the source of the problem, making fixing these issues simple.

@brendt brendt marked this pull request as draft February 17, 2026 08:06
@xHeaven xHeaven force-pushed the view-includes branch 2 times, most recently from 593eb19 to cd4d903 Compare February 17, 2026 11:29
@innocenzi innocenzi changed the title feat(view): use PHP's includes refactor(view): use PHP's includes Feb 17, 2026
}

private function makeElement(Token $token, ?Element $parent): ?Element
public function make(Token $token, Element $parent): ?Element
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ElementFactory now always requires a parent/root element

}

$children = [];
$element->setParent($parent);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored parent/child setting because not all elements have children, but all have a parent.

{
$this->parent = $parent;

$this->parent->setChildren([...$this->parent->getChildren(), $this]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See before: not all elements have children but all have a parent

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Represents a block of PHP code, currently only used to extract imports


public function getImports(): array
{
preg_match_all('/^\s*use .*;/m', $this->content, $matches);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently we're still using a regex, we could improve if needed once this refactor works

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new RootElement is used as… the root.

It ensures a ViewComponentElement has a parent where it can gather imports from

{
$imports = [];

foreach ($this->children as $child) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only want to resolve imports from PhpElements, not from sibling ViewComponent elements. That's why we check instanceof PhpElement here

return sprintf('new \%s([%s])', ImmutableArray::class, implode(', ', $entries));
}

public function getImports(): array
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View components can be nested, and we need to recursively resolve all imports.

Writing this reminds me: we also need to check for sibling PhpElements in the same file still. That's still TODO


// 4. Map to elements
$elements = $this->mapToElements($ast);
$rootElement = $this->mapToElements($ast);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactoring to accomodate the new RootElement

@brendt brendt changed the title refactor(view): use PHP's includes refactor(view): improved view component rendering Feb 18, 2026
@brendt brendt changed the title refactor(view): improved view component rendering refactor(view)!: improved view component rendering Feb 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Colliding class names in view imports

2 participants

Comments