Laravel子父表查询报错:where子句中product_name列不存在
问题:搜索库存时出现「Unknown column 'product_name' in 'where clause'」错误
构建搜索框和日历筛选功能时,执行搜索出现报错:Unknown column 'product_name' in 'where clause'
相关代码
父模型 Products
class Products extends Model { use SoftDeletes; protected $table = 'products'; protected $primaryKey = 'id'; protected $fillable = [ 'product_image', 'product_name', 'product_details', 'product_price', 'product_description' ]; public function inventory() { return $this->hasMany(Inventory::class); } }
子模型 Inventory
class Inventory extends Model { use SoftDeletes; protected $table = 'inventory'; protected $primaryKey = 'id'; protected $fillable = [ 'area', 'code', 'best_before', 'in_date', 'in_qty', 'out_date', 'out_qty' ]; public function products() { return $this->belongsTo(Products::class); } }
搜索控制器代码
public function search() { $other = $_GET['other']; $fromDate = $_GET['fromDate']; $toDate = $_GET['toDate']; $inventory = Inventory::with('products') ->where('in_date', '>=', $fromDate.'%') ->where('out_date', '<=', $toDate.'%') ->where('area', 'LIKE', '%'.$other.'%') ->orWhere('code', 'LIKE', '%'.$other.'%') ->orWhere('product_name', 'LIKE', '%'.$other.'%') ->get(); return view('inventory.search', compact('inventory')); }
迁移文件
Products 表迁移
public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string("product_image"); $table->string("product_name"); $table->string("product_details"); $table->string("product_description"); $table->string("product_price"); $table->softDeletes(); $table->timestamps(); }); }
Inventory 表迁移
public function up() { Schema::create('inventory', function (Blueprint $table) { $table->id(); $table->foreignId('products_id') ->constrained('products') ->onDelete('cascade') ->onUpdate('cascade'); $table->string("area"); $table->string("code"); $table->date("best_before"); $table->date("in_date"); $table->integer("in_qty"); $table->date("out_date")->nullable(); $table->integer("out_qty")->nullable(); $table->softDeletes(); $table->timestamps(); }); }
错误原因
product_name属于products表,并非inventory表字段。直接在Inventory查询中使用where('product_name', ...),会让MySQL尝试在inventory表中查找该字段,导致报错。- 原代码逻辑存在漏洞:
where与orWhere混用会破坏日期筛选规则——只要匹配到code或其他「或条件」,就会完全忽略日期范围限制,这也是你替换成products_id后搜索功能异常的原因。
解决方案
1. 修正关联搜索与逻辑结构
使用 whereHas 关联 products 表筛选product_name,同时用闭包包裹所有「或条件」,确保日期筛选始终生效。修改后的控制器代码:
public function search() { $other = $_GET['other']; $fromDate = $_GET['fromDate']; $toDate = $_GET['toDate']; $inventory = Inventory::with('products') // 固定日期范围筛选 ->where('in_date', '>=', $fromDate) ->where('out_date', '<=', $toDate) // 用闭包包裹所有关键词搜索的或条件,避免逻辑混乱 ->where(function ($query) use ($other) { $query->where('area', 'LIKE', '%'.$other.'%') ->orWhere('code', 'LIKE', '%'.$other.'%') // 关联products表,搜索产品名称 ->orWhereHas('products', function ($subQuery) use ($other) { $subQuery->where('product_name', 'LIKE', '%'.$other.'%'); }); }) ->get(); return view('inventory.search', compact('inventory')); }
2. 额外优化建议
- 避免直接使用
$_GET,改用Laravel的请求类更安全规范:use Illuminate\Http\Request; public function search(Request $request) { $other = $request->input('other'); $fromDate = $request->input('fromDate'); $toDate = $request->input('toDate'); // 后续逻辑同上 } - 日期筛选无需添加
%,因为in_date是date类型,直接用>=和<=即可准确匹配。
内容的提问来源于stack exchange,提问作者Asyuiop
相关产品推荐
相关产品推荐

