Laravel Boost Best Practices
Expert Laravel development guidelines curated for Laravel 12 applications with Livewire 3, Filament v4, and Pest testing framework.
Package Versions
This skill is optimized for:
PHP 8.4.13Laravel Framework v12Filament v4Livewire v3Pest v3Laravel Sanctum v4Tailwind CSS v4Alpine.js v3Core Principles
Code Conventions
Follow existing code conventions in the codebaseCheck sibling files for correct structure, approach, and naming before creating new filesUse descriptive names: `isRegisteredForDiscounts()`, not `discount()`Reuse existing components before writing new onesDo not create verification scripts when tests already cover the functionalityArchitecture
Stick to existing directory structure - don't create new base folders without approvalDo not change dependencies without approvalOnly create documentation files when explicitly requestedFrontend Bundling
If frontend changes aren't reflected, run `npm run build`, `npm run dev`, or `composer run dev`Laravel Boost MCP Tools
Laravel Boost provides powerful MCP server tools designed for this application:
**`list-artisan-commands`** - Check available Artisan command parameters before running**`get-absolute-url`** - Get correct scheme, domain/IP, and port for project URLs**`tinker`** - Execute PHP to debug code or query Eloquent models**`database-query`** - Read from database directly**`browser-logs`** - Read browser logs, errors, and exceptions (recent logs only)**`search-docs`** - Search version-specific documentation for Laravel ecosystem packagesDocumentation Search
**CRITICAL:** Use `search-docs` before making code changes to ensure correct approach.
**Best Practices:**
Pass array of packages to filter if you know which packages you needUse multiple, broad, simple, topic-based queries: `['rate limiting', 'routing rate limiting', 'routing']`Do NOT add package names to queries (already shared automatically): use `test resource table`, not `filament 4 test resource table`**Search Syntax:**
1. Simple word searches: `authentication` (auto-stemming finds 'authenticate', 'auth')
2. Multiple words (AND): `rate limit` (finds both "rate" AND "limit")
3. Quoted phrases: `"infinite scroll"` (exact adjacent match)
4. Mixed: `middleware "rate limit"` (both terms required)
5. Multiple queries: `["authentication", "middleware"]` (ANY match)
PHP Standards
General
Always use curly braces for control structures, even single-lineUse PHP 8 constructor property promotion: `public function __construct(public GitHub $github) {}`No empty `__construct()` methods with zero parametersType Declarations
Always use explicit return type declarationsUse appropriate PHP type hints for parameters```php
protected function isAccessible(User $user, ?string $path = null): bool
{
// ...
}
```
Documentation
Prefer PHPDoc blocks over inline commentsAdd useful array shape type definitions when appropriateAvoid inline comments unless code is very complexEnums
Use TitleCase for enum keys: `FavoritePerson`, `BestLake`, `Monthly`Laravel 12 Best Practices
File Structure (Streamlined Since Laravel 11)
**No** `app/Http/Middleware/` files**No** `app/Console/Kernel.php`Middleware, exceptions, routing: configure in `bootstrap/app.php`Service providers: register in `bootstrap/providers.php`Console configuration: `bootstrap/app.php` or `routes/console.php`Commands auto-register from `app/Console/Commands/`Artisan Commands
Use `php artisan make:` commands to create new filesPass `--no-interaction` to ensure commands work without user inputPass correct `--options` for proper behaviorUse `artisan make:class` for generic PHP classesList available commands with `list-artisan-commands` toolDatabase & Eloquent
**Relationships:**
Use proper Eloquent relationship methods with return type hintsPrefer relationships over raw queries or manual joinsAvoid `DB::`; prefer `Model::query()`Prevent N+1 queries with eager loadingUse query builder only for very complex operations**Migrations:**
When modifying columns, include ALL previously defined attributes or they'll be dropped**Laravel 11+ Features:**
Limit eagerly loaded records natively: `$query->latest()->limit(10);`**Models:**
Use `casts()` method instead of `$casts` property (follow existing conventions)Create useful factories and seeders when creating new modelsAPIs & Resources
Default to Eloquent API Resources with API versioningFollow existing API conventions if already establishedControllers & Validation
Always create Form Request classes for validation (not inline)Include both validation rules and custom error messagesCheck sibling Form Requests for array vs string-based validation styleQueues
Use queued jobs with `ShouldQueue` interface for time-consuming operationsAuthentication & Authorization
Use Laravel's built-in features: gates, policies, SanctumURL Generation
Prefer named routes and `route()` functionConfiguration
**Never** use `env()` outside config filesAlways use `config('app.name')`, not `env('APP_NAME')`Testing
Use model factories in testsCheck for custom factory states before manual setupUse Faker: `$this->faker->word()` or `fake()->randomDigit()` (follow existing convention)Create tests with `php artisan make:test <name>` (feature test) or `--unit` flag (unit test)Most tests should be feature testsVite
If frontend changes don't appear, run `npm run build` or ask user to run `npm run dev` / `composer run dev`Livewire 3
Core Principles
State lives on the server, UI reflects itAll requests hit Laravel backend like regular HTTP requestsAlways validate form data and run authorization checks in actionsComponents require single root elementCreating Components
```bash
php artisan make:livewire Posts\\CreatePost
```
Key Changes from Livewire 2
`wire:model.live` for real-time updates (`wire:model` is deferred by default)Components use `App\Livewire` namespace (not `App\Http\Livewire`)Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`)Use `components.layouts.app` view as typical layout path (not `layouts.app`)New Directives
Available: `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target`Best Practices
Use `wire:loading` and `wire:dirty` for loading statesAdd `wire:key` in loops:```blade
@foreach ($items as $item)
<div wire:key="item-{{ $item->id }}">
{{ $item->name }}
</div>
@endforeach
```
Lifecycle Hooks
```php
public function mount(User $user) {
$this->user = $user;
}
public function updatedSearch() {
$this->resetPage();
}
```
Alpine.js
Alpine is included with Livewire (don't manually include)Included plugins: persist, intersect, collapse, focusLivewire Initialization Hook
```javascript
document.addEventListener('livewire:init', function () {
Livewire.hook('request', ({ fail }) => {
if (fail && fail.status === 419) {
alert('Your session expired');
}
});
Livewire.hook('message.failed', (message, component) => {
console.error(message);
});
});
```
Testing Livewire
```php
Livewire::test(Counter::class)
->assertSet('count', 0)
->call('increment')
->assertSet('count', 1)
->assertSee(1)
->assertStatus(200);
// Testing component exists on page
$this->get('/posts/create')
->assertSeeLivewire(CreatePost::class);
```
Pest Testing
General
All tests written using Pest: `php artisan make:test --pest <name>`Never remove tests or test files without approvalTest all happy paths, failure paths, and edge casesTests live in `tests/Feature` and `tests/Unit`Basic Pest Test
```php
it('is true', function () {
expect(true)->toBeTrue();
});
```
Running Tests
All tests: `php artisan test`Single file: `php artisan test tests/Feature/ExampleTest.php`Filter by name: `php artisan test --filter=testName`Run minimal tests with appropriate filter before finalizing editsAsk user if they want full test suite after related tests passAssertions
Use specific methods instead of generic status codes:
```php
it('returns all', function () {
$response = $this->postJson('/api/docs', []);
$response->assertSuccessful(); // Not assertStatus(200)
});
```
Other specific assertions: `assertForbidden`, `assertNotFound`, etc.
Mocking
Import Pest mock function: `use function Pest\Laravel\mock;`Or use `$this->mock()` if existing tests doLaravel Pint
**Always run** `vendor/bin/pint --dirty` before finalizing changesDo NOT run `vendor/bin/pint --test`Simply run `vendor/bin/pint` to fix formatting issuesCode Quality Checklist
Before finalizing any changes:
1. ✅ Follow existing code conventions
2. ✅ Use descriptive variable/method names
3. ✅ Add proper type declarations
4. ✅ Create Form Requests for validation
5. ✅ Use Eloquent relationships properly
6. ✅ Prevent N+1 queries with eager loading
7. ✅ Write/update Pest tests for features
8. ✅ Run `vendor/bin/pint --dirty`
9. ✅ Run filtered tests: `php artisan test --filter=relevantTest`
10. ✅ Check if `npm run build` needed for frontend changes
Common Pitfalls to Avoid
❌ Using `env()` outside config files❌ Inline validation instead of Form Requests❌ Raw `DB::` queries instead of Eloquent❌ Missing `wire:key` in Livewire loops❌ Forgetting to eager load relationships❌ Creating verification scripts when tests exist❌ Changing dependencies without approval❌ Using generic `assertStatus()` instead of specific assertions