使用 Laravel Eloquent 查找列与数组匹配的记录

问题描述 投票:0回答:1

我正在努力寻找一种方法来检查数组转换列上现有的 WHERE 约束。

我的 Thread 模型有一个电话号码列表...

class Thread extends Model
{
    protected $casts = [
        'phone_numbers' => 'array'
    ];
}

所以我的桌子看起来像

+---------------------------------+
| `phone_numbers` VARCHAR(256)    |
+---------------------------------+
| ["+15552345678","+15559876543"] |
| ["+15558675309"]                |
+---------------------------------+

为了避免使用相同的电话号码重复线程,我使用

firstOrCreate
:

$phone_numbers = ["+15559876543","+15552345678"];
sort($phone_numbers); // always sort in case numbers are out of order
$thread = Thread::firstOrCreate(['phone_numbers' => $phone_numbers]);

正如您可能已经猜到的,这无法检测到现有记录,因为

phone_numbers
列只是数据库中的一个字符串,遗憾的是
firstToCreate
不够聪明,无法根据模型规则强制转换
$phone_numbers
,所以它不会匹配。

我想我可能只是手动转换

$phone_numbers
:

...
$thread = Thread::firstOrCreate(['phone_numbers' => json_encode($phone_numbers)]);

但这创建了一个转义字符串:

+---------------------------------------+
| `phone_numbers` VARCHAR(256)          |
+---------------------------------------+
| ["+15552345678","+15559876543"]       |
| ["+15558675309"]                      |
| "[\"+15552345678\",\"+15559876543\"]" | <-- new row
+---------------------------------------+

1)有没有一种 Laravel 方法可以进行这种比较,而无需手动将数组转换为字符串,或者

2)如何像 Eloquent 那样进行转换?我无法通过源码挖掘弄清楚它。

laravel eloquent
1个回答
0
投票

有一种方法,它不涉及手动对 json 进行排序。 MySQL 有一些可能令人感兴趣的 json 函数,即

JSON_CONTAINS
JSON_OVERLAPS
(最后一个仅在 MySQL 8 上可用)

$phone_numbers = ["+15559876543","+15552345678"];

$thread = Thread::query()
    ->whereRaw('JSON_CONTAINS(phone_numbers, ?)', [json_encode($phone_numbers)])
    ->firstOrCreate(
        [],
        ['phone_numbers' => $phone_numbers],
    );

您实际上并不需要对

$phone_numbers
进行排序才能使
JSON_CONTAINS()
正常工作。如果您确实希望对
phone_numbers
列进行“排序”,您可能无论如何都想这样做。

© www.soinside.com 2019 - 2024. All rights reserved.