Write class-based PHP components as HTML-like elements in files processed by Vite.
This plugin converts component tags into calls to nititech/html-components before vite-plugin-php executes the PHP.
<components.Button type="submit">
Save changes
</components.Button>becomes:
<?php $c_123456789 = new \components\Button(['type' => 'submit']); ?>
Save changes
<?php $c_123456789->close(); ?>- Vite
>6.0.0 vite-plugin-php>=3.0.0- PHP
>=7.0with Composer nititech/html-components
Prop spreading uses PHP array unpacking with string keys and requires PHP >=8.1.
Install the Vite plugins:
npm install --save-dev vite-plugin-php vite-plugin-php-componentsInstall the PHP component library:
composer require nititech/html-componentsLoad Composer's autoloader from your PHP entry point. Your application components must also be available through Composer or another autoloader.
<?php
require __DIR__ . '/vendor/autoload.php';Add both plugins to your Vite config. transpilePHPComponents() must come before usePHP() so component tags are transpiled before PHP runs.
// vite.config.ts
import { defineConfig } from 'vite';
import transpilePHPComponents from 'vite-plugin-php-components';
import usePHP from 'vite-plugin-php';
export default defineConfig({
plugins: [transpilePHPComponents(), usePHP()],
});The plugin checks for vendor/nititech/html-components under the Vite project root when a build starts. If your Composer dependencies live elsewhere, disable that check:
transpilePHPComponents({
skipLibCheck: true,
});Disabling the check does not remove the runtime dependency on nititech/html-components.
Use a dot-separated tag name to address a namespaced PHP class. For example,
<layouts.Centered> maps to \layouts\Centered.
<layouts.Centered
title="Search"
query="<?= $_GET['query'] ?? ''; ?>">
<components.Button type="submit">
Search
</components.Button>
</layouts.Centered>The plugin converts paired components into a constructor call and a matching close() call:
<?php $c_123456789 = new \layouts\Centered([
'title' => 'Search',
'query' => $_GET['query'] ?? '',
]); ?>
<?php $c_987654321 = new \components\Button(['type' => 'submit']); ?>
Search
<?php $c_987654321->close(); ?>
<?php $c_123456789->close(); ?>The generated variable names are internal implementation details. The examples use placeholders for readability; generated output uses inline PHP calls.
Components without child content use the static closed() method:
<components.Icon name="search" />becomes:
<?php \components\Icon::closed(['name' => 'search']); ?>Static values become PHP strings:
<components.Button type="submit" class="button-primary" />A value containing only a PHP output block stays a native PHP expression:
<components.Message variant="<?= $variant; ?>" />You can also mix text and PHP in one value:
<components.Avatar class="avatar avatar-<?= $size; ?>" />Use the ... attribute to merge an array into the component props:
<components.Button
...="<?= ['type' => 'submit', 'disabled' => $isDisabled]; ?>"
class="button-primary">
Save
</components.Button>Explicit props that follow the spread use PHP array unpacking semantics.
Prop spreading is useful when a component forwards selected props to another component:
<?php
namespace components;
class StyledButton extends \HTML\Component {
public function render() {
?>
<components.Button
...="<?= $this->__props__->filter(['*', '!class']); ?>"
class="button-primary">
<?= $this->children; ?>
</components.Button>
<?php
}
}See the nititech/html-components prop documentation for filtering and escaping behavior.
You can use the same syntax to spread attributes onto standard HTML elements:
<button
...="<?= $this->__props__->filter(['*', '!class']); ?>"
class="button-primary">
<?= $this->children; ?>
</button>The plugin rewrites a native element with a spread attribute to the library's \HTML\Element component, then transpiles it like any other component:
<HTML.Element
element="button"
...="<?= $this->__props__->filter(['*', '!class']); ?>"
class="button-primary">
<?= $this->children; ?>
</HTML.Element>The rewrite handles paired elements and common HTML void elements such as img, input, and meta. Native elements without a ... attribute remain unchanged.
Avoid entity-encoded double quotes such as " in other attributes on a native element that uses spreading.
The current rewrite reconstructs parsed attributes with double-quoted values and cannot preserve that case safely.
Report bugs and request features in the GitHub issue tracker.
If this project helps you, you can support its continued development:
| Ko-fi | Buy Me a Coffee | PayPal |
|---|---|---|
| Support on Ko-fi | Buy me a coffee | Donate with PayPal |