Skip to main content
Component classes let you run PHP logic before a component renders. You define a class with a mount() method, Lex calls it with the component’s props, and all public properties on the class instance are then available as variables inside the component template.

How class mounting works

  1. Lex resolves the component class for the tag (by explicit registration or auto-discovery).
  2. It instantiates the class.
  3. It calls mount(), injecting props by parameter name using reflection. Parameters with default values are used when the matching prop is absent.
  4. All public properties of the class instance are merged into the template scope alongside the passed props.
Public class properties are merged after the raw props. If a class property and a prop share the same name, the class property wins.

Writing a component class

Create a class with a mount() method. Declare public properties for any values you want to expose to the template:
app/View/Components/AlertComponent.php
namespace App\View\Components;

final class AlertComponent
{
    public string $icon    = '';
    public string $classes = '';

    public function mount(string $type = 'info', bool $dismissible = false): void
    {
        $this->icon = match ($type) {
            'success' => '✓',
            'error'   => '✖',
            default   => 'ℹ',
        };

        $this->classes = "alert alert-{$type}"
            . ($dismissible ? ' alert-dismissible' : '');
    }
}
The corresponding template can access both the original props ($type, $dismissible) and the class’s public properties ($icon, $classes):
views/components/alert.lex
<!-- Props: $type, $dismissible  |  Class properties: $icon, $classes -->
<div class="{{ $classes }}">
  <span>{{ $icon }}</span>
  {!! $slot !!}
  #if ($dismissible)
    <button class="close">&times;</button>
  #endif
</div>
Usage in a parent template:
<Alert type="success" dismissible />

Setting the class namespace

Call componentClassNamespace() with the base namespace where your component classes live. Lex uses this namespace for auto-discovery:
$lexer->componentClassNamespace('App\\View\\Components');
This is typically called once in your application bootstrap alongside other Lexer configuration.

Auto-discovery convention

When a namespace is set, Lex builds the class name from the component tag by normalizing it to PascalCase and appending Component:
TagClass resolved
<Alert />App\View\Components\AlertComponent
<alert />App\View\Components\AlertComponent
<card-name />App\View\Components\CardNameComponent
<UserProfile />App\View\Components\UserProfileComponent
The Component suffix is required. A class named App\View\Components\Alert will not be found by auto-discovery — only App\View\Components\AlertComponent will. This prevents accidental collisions with non-component classes in the same namespace.
If no matching class exists for a component, Lex renders the component normally from props alone — no error is thrown.

Explicit class registration

To register a component class by name instead of relying on auto-discovery:
$lexer->registerComponentClass('Alert', App\View\Components\AlertComponent::class);
Explicit registration takes priority over namespace-based auto-discovery.

Prop injection rules

Lex uses ReflectionMethod to inspect mount() and injects props by parameter name:
  • If the component was passed a prop whose name matches a mount() parameter, that value is used.
  • If no matching prop was passed but the parameter has a default value, the default is used.
  • Parameters with no matching prop and no default are not passed — PHP’s own default handling applies.

Full example

1

Create the component class

app/View/Components/AlertComponent.php
namespace App\View\Components;

final class AlertComponent
{
    public string $icon    = '';
    public string $classes = '';

    public function mount(string $type = 'info', bool $dismissible = false): void
    {
        $this->icon = match ($type) {
            'success' => '✓',
            'error'   => '✖',
            default   => 'ℹ',
        };

        $this->classes = "alert alert-{$type}"
            . ($dismissible ? ' alert-dismissible' : '');
    }
}
2

Create the component template

views/components/alert.lex
<div class="{{ $classes }}">
  <span>{{ $icon }}</span>
  {!! $slot !!}
  #if ($dismissible)
    <button class="close">&times;</button>
  #endif
</div>
3

Register the namespace

$lexer->componentClassNamespace('App\\View\\Components');
Lex will now find AlertComponent automatically whenever it encounters <Alert>.
4

Use the component in a template

<Alert type="success" dismissible>
  Your profile has been updated.
</Alert>

<Alert type="error">
  Failed to save changes.
</Alert>

Without a component class

Component classes are optional. If you don’t need PHP logic, omit the class entirely — the component template receives props directly as variables. See Components for the full props reference.

Build docs developers (and LLMs) love