Loading...
Loading...
Compare original and translation side by side
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRSTNO 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());SQLSTATE[23000]: Integrity constraint violation
→ 检查外键约束,而非代码bug
Class 'App\Models\Post' not found
→ 检查命名空间,运行composer dump-autoload
Method Illuminate\Database\Eloquent\Collection::save does not exist
→ get()返回Collection,而非Model。使用first()或update()# 主Laravel日志
tail -f storage/logs/laravel.log
# 查找特定错误
grep "SQLSTATE" storage/logs/laravel.log
# 日志过大时清空
> storage/logs/laravel.logAPP_DEBUG=true
APP_ENV=localcomposer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
# 访问地址 /telescope
# 查看:请求、查询、任务、事件、异常# 哪些变更可能导致此问题?
git log --oneline -10
git diff HEAD~5
# 检查迁移是否已执行
php artisan migrate:status
# 检查配置是否已缓存
php artisan config:show# 能否每次都触发问题?
php artisan tinker
>>> App\Models\Post::first();
# 在不同环境中尝试
APP_ENV=testing php artisan test// 启用查询日志
DB::listen(function ($query) {
Log::debug('Query executed', [
'sql' => $query->sql,
'bindings' => $query->bindings,
'time' => $query->time,
]);
});
// 或在特定代码中启用
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
}# 搜索类似的可行代码
grep -r "belongsTo" app/Models/
grep -r "middleware" app/Http/
# 查看Laravel文档中的模式
# 检查其他可正常工作的模型// ❌ 当前代码
class Post extends Model {
public function author() {
return $this->hasOne(User::class, 'id', 'user_id');
}
}
// ✅ Laravel约定写法
class Post extends Model {
public function user(): BelongsTo {
return $this->belongsTo(User::class);
}
}// 可正常工作的模型
class User extends Model {
protected $fillable = ['name', 'email'];
}
// 有问题的模型 - 差异:缺少批量赋值保护
class Post extends Model {
// 未定义$fillable或$guarded
}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 1假设:“文章无法保存是因为批量赋值保护阻止了'user_id'字段”
预期结果:将'user_id'添加到$fillable中可解决问题// 之前的代码(有问题)
protected $fillable = ['title', 'content'];
// 测试变更(仅修改一个变量)
protected $fillable = ['title', 'content', 'user_id'];
// 不要同时修改多个内容php artisan tinker
>>> $post = Post::create(['title' => 'Test', 'content' => 'Test', 'user_id' => 1]);
>>> $post->user_id; // 应返回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.use 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);
});
// 运行测试,先确认它会失败
php artisan test --filter=user_can_create_post// 针对根本原因的单一修复
protected $fillable = ['title', 'content', 'user_id'];
// 不要附带其他改进,比如:
// - 添加类型转换
// - 重构方法
// - 修改其他代码# 测试现在应通过
php artisan test --filter=user_can_create_post
# 所有测试仍需通过
php artisan test
# 手动验证
php artisan tinker
>>> $post = Post::create([...]);表明架构存在问题的模式:
- 每次修复都会暴露出新的共享状态/耦合
- 修复需要“大规模重构”
- 每次修复都会在其他地方产生新的症状
停止并质疑基础问题:
- 这个Laravel模式是否正确?
- 我们是否应该使用不同的方法(仓库/服务模式)?
- 我们是否在与框架作对?
在尝试更多修复前与团队讨论。// 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());// 查看实际执行的SQL
$posts = Post::where('status', 'published');
dd($posts->toSql(), $posts->getBindings());
// 检查关系是否已加载
$post = Post::first();
$post->relationLoaded('user'); // false
$post->load('user');
$post->relationLoaded('user'); // true
// 防止懒加载(捕获N+1问题)
Model::preventLazyLoading(!app()->isProduction());undefinedundefinedroute('posts.show', 1);
undefinedroute('posts.show', 1);
undefinedundefinedundefinedDB::table('jobs')->first();
undefinedDB::table('jobs')->first();
undefined// See exact validation errors
protected function failedValidation(Validator $validator)
{
Log::debug('Validation failed', [
'errors' => $validator->errors()->toArray(),
'input' => $this->all(),
]);
parent::failedValidation($validator);
}// 查看具体的验证错误
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 reduced阶段1:检测问题
- 启用Model::preventLazyLoading()
- 抛出异常显示问题所在
阶段2:找到模式
- 查看使用with()的可行代码
- 确定哪个关系在懒加载
阶段3:提出假设
- “添加with('user')可以解决N+1问题”
阶段4:修复
- 编写统计查询次数的测试
- 在查询中添加with('user')
- 验证查询次数已减少Phase 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'; }阶段1:调查
- 检查路由定义:/posts/{post}
- 检查控制器参数:Post $post
- 检查是否使用了自定义键
阶段2:模式对比
- 与可行的路由绑定对比
- 检查Post模型的getRouteKeyName()方法
阶段3:提出假设
- “参数名称不匹配或模型未找到”
阶段4:修复
- 确保路由参数与方法参数匹配
- 或自定义: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阶段1:错误提示“将[字段]添加到fillable属性中”
阶段2:检查其他模型的$fillable数组
阶段3:假设:“字段未在$fillable中”
阶段4:将字段添加到$fillable,测试| 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 |
| 阶段 | Laravel特定操作 | 成功标准 |
|---|---|---|
| 1. 根本原因 | 查看日志、Telescope、Tinker、最近变更 | 理解问题是什么及为什么发生 |
| 2. 模式分析 | 查找Laravel可行示例、查看文档 | 找出差异点 |
| 3. 假设验证 | 形成理论、在Tinker中测试 | 假设得到确认或形成新假设 |
| 4. 实施修复 | 编写Pest测试、修复、验证 | Bug已解决,测试通过 |