On Tue, Jul 14, 2026 at 7:31 PM Liam Hammett
<[email protected]> wrote:
>
> Hi internals,
>
> I'd like to open discussion on a new RFC, "Native Markup Expressions":
>
> RFC: https://wiki.php.net/rfc/native_markup_expressions
> Implementation (with tests): https://github.com/php/php-src/pull/22661
>
> It proposes a native syntax for HTML fragments as first-class PHP expressions,
> akin to how the frontend community has adopted JSX, with composition and
> escape-by-default output:
>
>
>     class Greeting implements Markup\Html
>     {
>         public function __construct(public string $name) {}
>
>         public function toHtml(): Markup\Html
>         {
>             return <>
>                 <h1 class="title">Hello, {$this->name}!</h1>
>                 <p>Welcome to PHP, where markup is a first-class
>                 expression.</p>
>             </>;
>         }
>     }
>
>     echo <Greeting name="Rasmus" />; // rendered HTML, values escaped
>
>
> Despite appearances, this is not a template language grafted onto the engine -
> the syntax is pure compile-time sugar. Every markup expression lowers
> during compilation to a plain `new` expression:
>
>
>     $html = <button class="btn">Sign in</button>;
>     // compiles to exactly:
>     $html = new \Markup\Element('button', ['class' => 'btn'], ['Sign in']);
>
>
> The RFC already answers many anticipated questions, and I am open
> to making further adjustments so this can become a feature the whole
> community benefits from.
>
> Looking forward to your feedback.
>
> Best regards,
> Liam

Cool! I'm reading through it now, and one thing gave me pause:

> Any tag whose name is capitalized, contains a namespace separator (), or 
> names a static method (::) is a component; everything else is a literal HTML 
> element.

Not so sure about that heuristic. PSR-4 is not a binding standard on
the language; class names can be lowercase, and therefore should be
valid as a component name. Instead of looking at whether the tag name
is capitalized, I'd think it would be better handled using the
standard fallback resolution strategy: look in the current namespace,
then look at imports, then global/root namespace, and only then
fallback to a literal HTML tag.

--
Garrett W.

Reply via email to