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

Laravel循环读取Seen模型属性报"Attempt to read property on null"错误

问题分析与解决

错误「Attempt to read property "seen" on null」的核心原因是:并非每个Rome的uuid都在Seen表中有对应记录。你循环外测试的是存在对应记录的uuid(比如IcHshOP2V),所以能正常运行,但循环遍历所有romeids时,遇到没有对应Seen记录的uuid,first()会返回null,直接访问$seen->seen就会触发错误。

修复步骤

1. 立即修复:增加空值检查

在访问$seen的属性前,先判断它是否存在:

foreach ($romeids as $uuid) {
    $seen = Seen::where('message', $uuid)
        ->where('user', $user)
        ->first();

    // 先判断$seen是否存在,不存在则跳过当前循环
    if (!$seen) {
        continue;
    }

    $wasseen = $seen->seen;

    if ($seen->seen === 0) {
        $seen->seen = 1;
        $seen->seen_at = Carbon::now();
        $seen->save();
    }
}

2. 性能优化:避免N+1查询

循环内每次执行数据库查询会导致N+1性能问题,建议先批量查询所有相关Seen记录,再在内存中匹配:

$user = Auth::id();
$romes = Rome::where('room', $request->id)->get();
$romeids = $romes->pluck('uuid')->toArray();

// 批量获取当前用户的所有相关Seen记录,并用uuid作为键快速查找
$seenRecords = Seen::whereIn('message', $romeids)
    ->where('user', $user)
    ->get()
    ->keyBy('message');

foreach ($romeids as $uuid) {
    $seen = $seenRecords->get($uuid);

    if (!$seen) {
        continue;
    }

    $wasseen = $seen->seen;

    if ($seen->seen === 0) {
        $seen->seen = 1;
        $seen->seen_at = Carbon::now();
        $seen->save();
    }
}

3. 可选:自动创建缺失的Seen记录

如果需要确保每个Rome消息都有对应的Seen记录,可以在查询不到时自动创建:

foreach ($romeids as $uuid) {
    // 用firstOrCreate自动创建缺失的记录,可自定义默认值
    $seen = Seen::firstOrCreate(
        ['message' => $uuid, 'user' => $user],
        ['seen' => 1, 'seen_at' => Carbon::now()]
    );

    $wasseen = $seen->seen;

    if ($seen->seen === 0) {
        $seen->seen = 1;
        $seen->seen_at = Carbon::now();
        $seen->save();
    }
}

另外注意:你当前返回的$wasseen只会保留循环最后一次的值,若需要返回所有消息的已读状态,建议将结果存入数组后再返回。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:30:04