livewire/volt
Volt is a functional API for Laravel Livewire that enables single-file components, keeping PHP component logic and Blade templates together in one file for a clean, streamlined developer experience.
Installation:
composer require livewire/volt
Volt integrates seamlessly with Livewire, requiring no additional configuration beyond ensuring Livewire is installed (livewire/livewire).
First Component: Create a Volt component using the Artisan command:
php artisan make:volt Counter
This generates a single-file component (resources/views/counter.volt.php) with both PHP logic and Blade template in one file.
Basic Usage:
// resources/views/counter.volt.php
<div>
<button wire:click="increment">Count: <?php echo $count; ?></button>
</div>
<?php
$count = 0;
public function increment()
{
$count++;
}
Render in Blade:
@volt('counter')
Volt excels at rapid development. For example, create a modal component:
php artisan make:volt Modal
<!-- resources/views/modal.volt.php -->
<div x-data="{ open: false }" x-show="open" class="modal">
<div class="modal-content">
<h2>Modal Title</h2>
<p>Modal content goes here.</p>
<button wire:click="close">Close</button>
</div>
</div>
<?php
public function close()
{
$this->dispatch('close-modal');
}
Component Structure:
Volt files (*.volt.php) combine PHP logic and Blade templates. Use <x-volt> directives for reusable fragments:
<div>
<h1><?php echo $title; ?></h1>
<x-volt:fragment name="content">
<!-- Reusable content -->
</x-volt:fragment>
</div>
<?php
$title = "Hello, Volt!";
State Management:
Use $this->state for persistent properties:
<?php
$this->state = [
'items' => [],
'search' => '',
];
public function addItem($item)
{
$this->items[] = $item;
}
Functional API: Leverage Volt’s facade for dynamic rendering:
use Livewire\Volt\Facades\Volt;
Volt::component('counter')
->with('count', 10)
->title(fn () => "Counter: {$this->count}");
Rules and Validation:
<?php
$this->rules = [
'email' => ['required', 'email'],
'password' => ['required', 'min:8'],
];
// Or with closures:
$this->rules = [
'email' => fn ($attribute, $value) => $value === 'test@example.com',
];
Route Binding:
<?php
public function mount($userId)
{
$this->user = User::findOrFail($userId);
}
Testing: Use Volt’s testing helpers:
$this->assertSeeVolt('Count: 10');
$this->assertDontSeeVolt('Error');
Class-Based Components:
Use --class flag with make:volt for class-based syntax:
php artisan make:volt UserProfile --class
<?php
class UserProfile extends Livewire\Component
{
public $name;
public function mount()
{
$this->name = auth()->user()->name;
}
public function render()
{
return view('livewire.user-profile', [
'name' => $this->name,
]);
}
}
Fragments: Reuse components across views:
// resources/views/partials/header.volt.php
<header>
<h1><?php echo $title; ?></h1>
</header>
<?php $title = "Dashboard"; ?>
@volt('partials.header')
Dynamic Components:
Volt::component('dynamic-component')
->withQueryParams(request()->query())
->actingAs(auth()->user());
View Path Configuration:
Ensure livewire.view_path in config/livewire.php points to your Volt components directory (e.g., resources/views). Volt uses this to resolve component paths.
'view_path' => resource_path('views'),
State vs. Properties:
$this->state['items']).$count = 0;).
Avoid mixing them unintentionally; use $this->state for shared data.Script Tags in Volt:
Volt treats <script> tags as part of the template. For dynamic scripts, use @stack or @push directives:
@push('scripts')
<script>
Livewire.on('event', () => { ... });
</script>
@endpush
Caching Issues: Clear Blade cache if components aren’t updating:
php artisan view:clear
php artisan cache:clear
Route Binding:
Volt components support route binding, but ensure the mount() method accepts the parameter:
public function mount($id) // Required for route binding
{
$this->post = Post::find($id);
}
Check Component Resolution:
Use php artisan livewire:discover to ensure Volt components are registered.
Log State: Add debug logs to track state changes:
public function someMethod()
{
\Log::info('State:', $this->state);
}
Test Volt Components:
Use Volt::test() in feature tests:
public function test_counter_component()
{
Volt::test('counter')
->assertSee('Count: 0')
->call('increment')
->assertSee('Count: 1');
}
Custom Directives: Extend Volt’s Blade directives by publishing the config:
php artisan vendor:publish --tag=volt-config
Then add custom directives in config/volt.php.
Precompiler Hooks:
Override Volt’s precompiler behavior by extending Livewire\Volt\Precompilers\Precompiler:
namespace App\Volt;
use Livewire\Volt\Precompilers\Precompiler;
class CustomPrecompiler extends Precompiler
{
public function compile($content)
{
// Custom logic
return parent::compile($content);
}
}
Register it in AppServiceProvider.
Class Component Overrides:
For class-based components, override the render() method to customize view logic:
public function render()
{
return view('custom.view', [
'data' => $this->state,
]);
}
Avoid Heavy Logic in mount():
Move expensive operations to hydrate() or lazy-load data:
public function hydrate()
{
$this->expensiveData = $this->loadExpensiveData();
}
Use wire:ignore:
Opt out of Livewire’s reactivity for static content:
<div wire:ignore>
<!-- Non-reactive content -->
</div>
Memoization: Cache computed properties:
public function getFilteredItemsProperty()
{
return $this->memoize('filteredItems', function () {
return $this->items->where('active', true);
});
}
How can I help you explore Laravel packages today?