
当 Eloquent 模型定义了 $with 属性实现自动预加载时,可通过 without() 方法在特定查询中精准移除指定关联,避免不必要的数据加载,提升性能。
当 eloquent 模型定义了 `$with` 属性实现自动预加载时,可通过 `without()` 方法在特定查询中精准移除指定关联,避免不必要的数据加载,提升性能。
在 Laravel 开发中,$with 属性是 Eloquent 提供的便捷机制,用于为模型声明「默认预加载」的关联关系。例如,在 AssessmentCategory 模型中设置:
protected $with = ['questions'];
意味着每次查询该模型(如 AssessmentCategory::all() 或 AssessmentCategory::find(1))时,框架会自动附加 with('questions'),强制加载所有关联的 AssessmentQuestion 数据。这虽简化了常见场景的代码,但也可能带来性能隐患——尤其当你仅需主表字段(如 ID、标题)而无需子数据时。
此时,Laravel 提供了灵活的解决方案:without() 查询构建器方法。它允许你在具体查询链中显式排除已声明的 $with 关系,实现按需控制加载行为。
✅ 正确用法示例:
// 仅获取 assessment_categories 表的 id 和 title 字段,且不加载 questions 关联
AssessmentCategory::without('questions')
->jsonColumns()
->get();⚠️ 注意事项:
- without() 接收字符串(单个关系)或字符串数组(多个关系),如 without(['questions', 'author']);
- 它仅影响当前查询链,不会修改模型的 $with 配置,也不影响其他查询;
- 若同时调用 with() 和 without(),without() 优先级更高(即后者会覆盖前者对该关系的加载);
- without() 必须在 get()、first() 等执行方法之前调用,否则无效;
- 不要与 loadMissing() 或 load() 混淆:without() 是“禁止加载”,而后两者是“主动补加载”。
? 小技巧:你还可以结合 withoutGlobalScopes() 或 withoutTrashed() 等方法构建更精细的查询策略,但针对 $with 场景,without() 是最直接、语义最清晰的选择。
总结:$with 是便利性设计,without() 是可控性保障。合理组合二者,既能享受默认预加载的简洁,又能规避 N+1 或冗余数据带来的性能损耗,体现 Laravel “约定优于配置,但绝不牺牲控制力”的设计哲学。










