Laravel Eloquent 显示后更新

Posted

技术标签:

【中文标题】Laravel Eloquent 显示后更新【英文标题】:Laravel Eloquent update after display 【发布时间】:2021-12-28 12:06:37 【问题描述】:

我在使用自定义通知模型(不是 Laravel 标准模型)时遇到了问题。

在我的控制器中,我获取所有通知并将它们保存到一个变量中。

之后,我将更新所有通知并设置 read_at 日期时间。

    public function index($showRead = null)
    
        $user = auth()->user();
        $notifications = $user->notifications()->latest()->paginate(10);
        $view = view('notification.index',['notifications'=>$notifications])->render();
        Notification::where('id_user',$user->id)->update(['read_at'=>now()]);
        return $view;
    

问题:

$notifications 集合确实包含 read_at NULL 条目,因为我在第二行获取数据。

但不知何故,更新也会刷新渲染视图。

我能以某种方式阻止这种情况吗?我想在第一页请求上显示未读通知,在下面的请求中,它们应该有时间戳

【问题讨论】:

可以分享一下视图刀片文件吗? 【参考方案1】:

在此查询中使用where() 条件来获取未读通知:$notifications = $user->notifications()->where('read_at', Null)->orderBy('created_at', 'DESC')->paginate(10);


阅读后更新通知的解决方案:

解决方案 1:

将未读通知存储到Laravel Collections 并压缩到视图:$notifications = $user->notifications()->latest()->paginate(10);

解决方案 2:

或者在您的视图刀片中运行此查询Notification::where('id_user',$user->id)->update(['read_at'=>now()]);

解决方案 3:

当用户将访问通知视图刀片时,发送 AJax 请求以更新通知。

【讨论】:

【参考方案2】:

您可以在通知上创建一个构建器(不要使用 get),然后将第一个构建器克隆到另一个变量中,之后您可以更新克隆的构建器并从原始构建器获取集合。

$notifsBuilder1= $user->notifications();
$notifsBuilder2 = clone $notifsBuilder1;
$notifs = $notifsBuilder1->latest()->paginate(10);
$notifsBuilder2->update(['read_at'=>now()])

【讨论】:

【参考方案3】:

进行此类操作的最简单方法是让您的前端向您的控制器发送一个 api 请求以读取某个通知。 你可以这样做:


class NotificationsController extends Controller
  public function index(Request $request, $showRead = null)
    $user = auth()->user();
    $notifications = Notification::where('user_id', $user->getKey())->latest()->orderBy('created_at')->paginate(10);
    return view('notifications.index', compact('notifications'));
  

  public function markAsRead(Notification $notification)
    $done = $notification->forceFill(['read_at' => now()]);
    return compact('done');
  



如果您使用的是 VueJs,那么您可以在前端内部使用它(不用担心,您也可以查找匹配的东西,如果不是):

在你的 Vue 组件内部使用 axios 库来处理请求,并为你的路由使用 ziggy 库:


let axios = require('axios');
let notifications = [];
let getNotifications = async () => 
  return axios.get(route('notifications.index')).then(res => 
    notifications = res.data.notifications;
  );

let markNotificationAsRead = (notification_id) => 
  axios.get(route('notification.read', ['notification' => notification_id]));


getNotifications();
for(let i = 0; i < notifications.length; i++)
  markNotificationAsRead(notifications[notification].id);


这样,您的所有通知都是通过您的 api 和您的 api 处理的,因为成像您的用户会要求通知,但在您将他的响应交给他之前取消了请求,他实际上会错过这些。

【讨论】:

以上是关于Laravel Eloquent 显示后更新的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 不使用 Eloquent 更新项目

Laravel eloquent 使用关系列更新列

Laravel 5.4:使用eloquent和fillable字段更新多个表的多个模型

Laravel Eloquent 保存项目

Laravel (Eloquent) 不更新数据库

如何在 laravel 5 中使用 Eloquent 更新数据透视表