tomasvotruba/bladestan
Bladestan brings PHPStan-powered static analysis to Laravel Blade templates. It catches template-related issues during analysis and offers a Blade error formatter with clickable template paths and “rendered in” context for faster debugging.
composer require tomasvotruba/bladestan --dev
phpstan.neon:
includes:
- vendor/tomasvotruba/bladestan/config/extension.neon
vendor/bin/phpstan analyze --error-format=blade
Debugging Undefined Blade Variables:
phpstan analyze on a controller returning a view with missing data:
return view('dashboard', ['user' => $user]); // Missing 'posts' key
------ -----------------------------------------------------------
Line resources/views/dashboard.blade.php
------ -----------------------------------------------------------
10 Undefined variable $posts.
passed in: DashboardController.php:15
------ -----------------------------------------------------------
$posts to the view data or update the template.CI/CD Pipeline:
Add to phpstan job in GitHub Actions:
- name: Run Bladestan
run: vendor/bin/phpstan analyze --error-format=blade --level=max
max level to enforce strict Blade validation.Local Development:
phpstan analyze --error-format=blade in pre-commit hooks (e.g., with husky).composer.json:
"scripts": {
"bladestan": "phpstan analyze --error-format=blade"
}
Livewire Component Validation:
<x-my-component :user="$user" /> <!-- Validates $user exists -->
Template Inheritance:
@extends or @section definitions:
@extends('layouts.app') <!-- Missing file or incorrect path -->
Custom Error Filtering:
phpstan.neon:
errorLevel[Bladestan\Rule\MissingTemplateRule] = ignore
Mail Template Analysis:
resources/views/emails/welcome.blade.php) by ensuring they’re included in View::make() calls.Dynamic Includes:
@include with dynamic paths:
@include($templatePath) <!-- Validates $templatePath is a valid view -->
Shared Data Validation:
View::share():
View::share('config', $config); // Validates $config is passed to all views
Cache Invalidation:
--clear-cache or configure in phpstan.neon:
cacheDirectory = ./phpstan-cache
Livewire Component Namespaces:
livewire.component.namespace in config/livewire.php matches your components.Dynamic Blade Logic:
@if/@foreach conditions may not be fully analyzed.False Positives:
$errors or $slot variables may trigger false alarms.errorLevel[Bladestan\Rule\UndefinedVariableRule] = ignore
Verbose Output:
--verbose to debug template parsing:
vendor/bin/phpstan analyze --error-format=blade --verbose
Line Number Accuracy:
@include files.@include paths are absolute (e.g., @include('partials.header')).PHPStan Version Conflicts:
composer.json:
"require-dev": {
"phpstan/phpstan": "^2.0",
"tomasvotruba/bladestan": "^0.11"
}
Custom Rules:
Bladestan\Rule\* to add project-specific validation (e.g., required fields in forms).Error Formatting:
phpstan.neon:
errorFormatter = Bladestan\ErrorFormatter\CustomFormatter
Template Paths:
config/view.php to include package views:
'paths' => [
resource_path('views'),
base_path('vendor/package/views'),
],
Livewire Props:
Bladestan\Livewire\LivewireExtension.How can I help you explore Laravel packages today?