You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel查询构建器方法及字段存储格式选型技术咨询

关于Laravel产品表操作的技术建议

嘿,我来帮你把这些问题捋清楚,一步步说哈~

一、替代PHP数组函数的Eloquent/查询构建器方案

你现在把数据库字段拉到PHP里用array_push/array_search/array_splice处理,其实完全没必要——Laravel和数据库本身就提供了更高效、更简洁的方式,不用把数据拿到应用层折腾:

  • 判断元素是否存在:直接用数据库的JSON查询或字符串匹配函数,在数据库层面完成判断,不用拉数据。
  • 插入/删除元素:用数据库的JSON操作函数,或者借助Eloquent的模型特性直接操作数组,自动同步到数据库。

二、A_product列存储格式:JSON完胜逗号分隔字符串

直接给结论:优先选择JSON格式存储,原因如下:

  • 类型安全:JSON是数据库原生支持的类型(比如MySQL的JSON类型),能明确存储数组结构,而逗号分隔的字符串本质是文本,容易出现格式错误(比如多逗号、空格、重复值)。
  • 查询更灵活:Laravel专门提供了whereJsonContains这类JSON查询方法,比FIND_IN_SET更强大,还能处理嵌套结构(以后扩展也方便)。
  • 开发效率高:在Eloquent模型里设置$casts属性后,Laravel会自动把JSON字段转成PHP数组,你直接操作数组就行,不用自己拆字符串、转格式。
  • 可扩展性强:如果以后需要给每个产品项加额外属性(比如数量、备注),JSON可以直接存对象数组,逗号分隔字符串根本做不到。

逗号分隔字符串属于数据库设计的反模式,后期维护成本极高,除非有特殊历史原因,否则坚决不推荐。

三、优化“判断id=1的A_product是否包含3”的代码

你当前的代码有个小错误:in_array("3")少了第二个参数(要传入拆分后的数组),而且这种方式效率低——不如直接在数据库层面完成判断:

方案1:JSON格式下的优雅实现

假设A_product存的是JSON数组(比如[4,5,8,9]),先在Product模型里加一行:

protected $casts = [
    'A_product' => 'array', // 自动把JSON转成PHP数组
];

然后判断代码可以写成:

// 用模型的方式
$product = Product::find(1);
$A_result = collect($product->A_product)->contains(3) ? '1' : '0';

// 或者用查询构建器直接查
$A_result = DB::table('product')
    ->where('id', 1)
    ->whereJsonContains('A_product', 3)
    ->exists() ? '1' : '0';

两种方式都不用把字段拉到PHP里拆数组,简洁又高效。

方案2:如果暂时用逗号分隔字符串(不推荐)

可以用MySQL的FIND_IN_SET函数直接查询:

$A_result = DB::table('product')
    ->where('id', 1)
    ->whereRaw('FIND_IN_SET(?, A_product)', [3])
    ->exists() ? '1' : '0';

这种方式比你原来拆数组的方法效率高,因为不用传输数据到应用层。

四、插入/修改元素的操作建议

1. JSON格式下的操作(推荐)

追加元素

用模型的话超级简单,直接操作数组再保存:

$product = Product::find(1);
$product->A_product[] = 12; // 直接追加元素
$product->save(); // Laravel自动转成JSON存回数据库

如果想用查询构建器批量更新:

DB::table('product')
    ->where('id', 1)
    ->update([
        'A_product' => DB::raw('JSON_ARRAY_APPEND(A_product, "$", ?)'),
    ], [12]);

删除元素

模型方式更直观:

$product = Product::find(1);
// 过滤掉要删除的元素,重新赋值
$product->A_product = collect($product->A_product)->reject(function ($item) {
    return $item == 5;
})->values()->toArray();
$product->save();

查询构建器方式用数据库函数:

DB::table('product')
    ->where('id', 1)
    ->update([
        'A_product' => DB::raw('JSON_REMOVE(A_product, JSON_UNQUOTE(JSON_SEARCH(A_product, "one", ?)))'),
    ], [5]);

2. 逗号分隔字符串下的操作(不推荐)

这种方式非常繁琐,容易出错,举个例子:

追加元素(要先判断是否存在,避免重复)

DB::table('product')
    ->where('id', 1)
    ->whereRaw('NOT FIND_IN_SET(?, A_product)', [12])
    ->update([
        'A_product' => DB::raw('CONCAT(A_product, ",?")'),
    ], [12]);

删除元素(容易误删类似值,比如删5会把15也改掉)

DB::table('product')
    ->where('id', 1)
    ->update([
        'A_product' => DB::raw('TRIM(BOTH "," FROM REPLACE(CONCAT(",", A_product, ","), ",5,", ","))'),
    ]);

这种写法维护起来太痛苦,真心不建议用。

五、终极建议:考虑数据库规范化

如果你的产品项需要频繁查询、修改,最好的方案是规范化数据库结构——创建一个关联表,比如product_associations:

idproduct_idproduct_valuetype
114A
215A
313B
............

然后在Product模型里定义关联:

public function aProducts()
{
    return $this->hasMany(ProductAssociation::class, 'product_id')
        ->where('type', 'A');
}

public function bProducts()
{
    return $this->hasMany(ProductAssociation::class, 'product_id')
        ->where('type', 'B');
}

这种方式的好处:

  • 可以给product_value加索引,查询效率爆表。
  • 操作更符合数据库设计规范,不会有JSON/字符串数组的各种坑。
  • 支持更复杂的查询(比如统计某个产品值出现的次数)。

当然,如果你的业务场景非常简单,JSON格式也足够用,但规范化是长期来看最靠谱的方案。

内容的提问来源于stack exchange,提问作者robspin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:22:19