Loading...
Loading...
Systematic debugging process for Laravel applications - ensures root cause investigation before attempting fixes. Use for any Laravel issue (test failures, bugs, unexpected behavior, performance problems).
npx skill4agent add iserter/laravel-claude-agents systematic-debugging-laravelNO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRSTSQLSTATE[23000]: Integrity constraint violation
→ Check foreign key constraints, not a code bug
Class 'App\Models\Post' not found
→ Check namespace, run composer dump-autoload
Method Illuminate\Database\Eloquent\Collection::save does not exist
→ get() returns Collection, not Model. Use first() or update()# Main Laravel log
tail -f storage/logs/laravel.log
# Check for specific errors
grep "SQLSTATE" storage/logs/laravel.log
# Clear logs if too large
> storage/logs/laravel.logAPP_DEBUG=true
APP_ENV=localcomposer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
# Access at /telescope
# View: Requests, Queries, Jobs, Events, Exceptions# What changed that could cause this?
git log --oneline -10
git diff HEAD~5
# Check if migrations ran
php artisan migrate:status
# Check if config cached
php artisan config:show# Can you trigger it every time?
php artisan tinker
>>> App\Models\Post::first();
# Try in different environments
APP_ENV=testing php artisan test// Enable query logging
DB::listen(function ($query) {
Log::debug('Query executed', [
'sql' => $query->sql,
'bindings' => $query->bindings,
'time' => $query->time,
]);
});
// Or in specific code
DB::enableQueryLog();
$posts = Post::with('user')->get();
dd(DB::getQueryLog());# Search for similar working code
grep -r "belongsTo" app/Models/
grep -r "middleware" app/Http/
# Check Laravel docs for the pattern
# Check other models that work correctly// ❌ What you have
class Post extends Model {
public function author() {
return $this->hasOne(User::class, 'id', 'user_id');
}
}
// ✅ Laravel convention
class Post extends Model {
public function user(): BelongsTo {
return $this->belongsTo(User::class);
}
}// Working model
class User extends Model {
protected $fillable = ['name', 'email'];
}
// Broken model - difference: missing mass assignment protection
class Post extends Model {
// No $fillable or $guarded defined
}Hypothesis: "Posts aren't saving because mass assignment
protection is blocking the 'user_id' field"
Expected: Adding 'user_id' to $fillable will fix it// Before (broken)
protected $fillable = ['title', 'content'];
// Test change (ONE variable)
protected $fillable = ['title', 'content', 'user_id'];
// Don't change multiple things at oncephp artisan tinker
>>> $post = Post::create(['title' => 'Test', 'content' => 'Test', 'user_id' => 1]);
>>> $post->user_id; // Should be 1use Illuminate\Foundation\Testing\RefreshDatabase;
test('user can create post', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)
->post('/posts', [
'title' => 'Test Post',
'content' => 'Test content',
]);
$response->assertRedirect();
expect(Post::where('title', 'Test Post')->exists())->toBeTrue();
expect(Post::first()->user_id)->toBe($user->id);
});
// Run and watch it FAIL first
php artisan test --filter=user_can_create_post// ONE fix for the root cause
protected $fillable = ['title', 'content', 'user_id'];
// NO bundled improvements like:
// - Adding casts
// - Refactoring methods
// - Changing other code# Test passes now
php artisan test --filter=user_can_create_post
# All tests still pass
php artisan test
# Manual verification
php artisan tinker
>>> $post = Post::create([...]);Pattern indicating architectural problem:
- Each fix reveals new shared state/coupling
- Fixes require "massive refactoring"
- Each fix creates new symptoms elsewhere
STOP and question fundamentals:
- Is this Laravel pattern correct?
- Should we use a different approach (repository/service)?
- Are we fighting the framework?
Discuss with team before attempting more fixes.// See actual SQL
$posts = Post::where('status', 'published');
dd($posts->toSql(), $posts->getBindings());
// Check relationship loading
$post = Post::first();
$post->relationLoaded('user'); // false
$post->load('user');
$post->relationLoaded('user'); // true
// Prevent lazy loading (catch N+1)
Model::preventLazyLoading(!app()->isProduction());# List all routes
php artisan route:list
# Find specific route
php artisan route:list --name=posts
# Check route exists
php artisan tinker
>>> route('posts.show', 1);# See failed jobs
php artisan queue:failed
# Retry failed job
php artisan queue:retry <id>
# Work queue with verbose output
php artisan queue:work --verbose
# Check job payload
php artisan tinker
>>> DB::table('jobs')->first();// See exact validation errors
protected function failedValidation(Validator $validator)
{
Log::debug('Validation failed', [
'errors' => $validator->errors()->toArray(),
'input' => $this->all(),
]);
parent::failedValidation($validator);
}Phase 1: Detect it
- Enable Model::preventLazyLoading()
- Exception thrown showing the problem
Phase 2: Find the pattern
- Check working code that uses with()
- Identify which relationship is lazy loading
Phase 3: Hypothesis
- "Adding with('user') will prevent the N+1"
Phase 4: Fix
- Add test that counts queries
- Add with('user') to the query
- Verify query count reducedPhase 1: Investigate
- Check route definition: /posts/{post}
- Check controller parameter: Post $post
- Check if using custom key
Phase 2: Pattern
- Compare with working route binding
- Check Post model for getRouteKeyName()
Phase 3: Hypothesis
- "Parameter name doesn't match or model not found"
Phase 4: Fix
- Ensure route parameter matches method parameter
- Or customize: public function getRouteKeyName() { return 'slug'; }Phase 1: Error says "Add [field] to fillable property"
Phase 2: Check other models' $fillable arrays
Phase 3: Hypothesis: "Field not in $fillable"
Phase 4: Add field to $fillable, test| Phase | Laravel-Specific Activities | Success Criteria |
|---|---|---|
| 1. Root Cause | Check logs, Telescope, Tinker, recent changes | Understand WHAT and WHY |
| 2. Pattern | Find working Laravel examples, check docs | Identify differences |
| 3. Hypothesis | Form theory, test in Tinker | Confirmed or new hypothesis |
| 4. Implementation | Create Pest test, fix, verify | Bug resolved, tests pass |