Laravel 5:更新多条记录

4
我有一个简单的待办事项应用程序,但无法同时持久化多个记录的更新。客户端版本在这里可以正常运行:http://codepen.io/anon/pen/bVVpyN 每次我执行操作时,都会向我的Laravel API发送HTTP请求以持久化数据。但是我在completeAll方法上遇到了问题。
每当我点击“全部完成”按钮时,就会执行completeAll方法:
completeAll: function () {
    var tasks = [];
    var taskIds = [];

    this.tasks = this.tasks.filter(function (task) {
        task.completed = true;
        tasks.push(task);
        taskIds.push(task.id);
        return task.completed;
    });

    this.$http.put('api/tasks/' + taskIds, { tasks: tasks });
},

我在这里向一个URL发送请求,它可能看起来像这样:

http://localhost:8000/api/tasks/1,3,8,4

同时,我会发送任务对象。这是来自 Chrome 开发者工具的请求有效载荷:

{tasks: [{id: 1, body: "One", completed: true, created_at: "2015-09-09 08:36:38",},]}

然后,在服务器端,我有一个名为 TasksController更新函数,代码如下:

public function update(Request $request, $id)
{
    // gives ["1", "2", "3"] instead of "1,2,3" a
    $taskIds = explode(",", $id);

    // what happens if I update more than one task at once
    // ** PROBLEMATIC SECTION **
    if (count($taskIds) > 1) {
        $tasks = Task::whereIn('id', $taskIds)->get()->toArray();
        $newTasks = Input::get('tasks');

        var_dump($tasks);
        var_dump($newTasks);

        /** This Line does not Work **/
        Task::whereIn('id', $taskIds)->update(Input::get('tasks'));

        return 'update more than one task at once';
    }

    // what happens if I update only one task
    Task::where('id', $id)->update(Input::all());

    return 'update exactly one task';
}

上述的$tasks$newTasks变量使用toArray()方法后,var_dump的结果相同。但是当我尝试更新任务时,出现了以下错误:
preg_replace(): Parameter mismatch, pattern is a string while replacement is an array

我不确定为什么。在我看来,Task::whereIn('id', $taskIds)是一个对象而不是字符串。

到目前为止我尝试过的替代方法

  1. 使用foreach/for循环遍历$tasks数组,但我无法使其工作,因为我还必须遍历$newTasks数组进行分配,像这样:

    foreach ($tasks as $task) { for ($i=0; $i < count($taskIds); $i++) { Task::where('id', $task->id)->update($newTasks[$i]) } }

  2. 在我的API上创建另一个端点,以完成每个任务,URL如下:

    http://localhost:8000/api/tasks/complete-all

然后在我的TasksController上执行一个completeAll方法,将每个任务设置为已完成。但我无法让它工作,因为我得到了一个

Method not allowed exception

我不确定为什么,但我认为使用像这样的API更好地使用我的原始方法:

api/tasks/1,2,50,1,3

因为在这里建议过:https://laracasts.com/discuss/channels/code-review/vuejs-delete-multiple-tasks-each-task-one-request


请就我的原始尝试提供建议,帮助我让这个简单的TodoApp工作。
或者,如果更好的话,请帮我让foreach/for循环起作用。谢谢。

编辑

根据一个答案,建议遵循上述第2点并创建一个额外的端点。

这是我的路由:

enter image description here

我使用post方法向url发送请求:

http://localhost:8000/api/tasks/complete-all

通过我的app.js执行,使用以下内容:

this.$http.post('api/tasks/complete-all');   

这是我改编后的TasksController:

public function completeAll(Request $request)
{
    $tasks = Task::where('completed', false)->get();

    foreach ($tasks as $task) {
       Task::where('id', $task->id)->update(['completed' => true]);
    }

    return response()->json(['message' => 'All tasks completed']);
}

应用程序现在正确地保留数据,但让我感到困扰的是,我并没有真正从客户端更新任何内容。我只是执行服务器端代码,因为我实际上没有传递任何查询。如何使用像这样的URL解决问题:
http://localhost:8000/api/tasks/1,23,43,5

谢谢


嗨,看起来你对问题的解释太宽泛了,你所说的持久化数据是什么意思?请同时解释一下你URL中的参数。 - Gokigooooks
1个回答

2
Laravel CRUD方法仅适用于单个资源。因此,向update发送多个资源不符合此要求。
虽然您可以更新update方法,但我鼓励您创建一个completeTaskscompleteAll方法,以处理多个资源。您可以在请求正文中传递多个资源。
要做到这一点,您需要:
  • 添加路由
  • 解析Todo ids的请求数据(例如使用for循环)
  • 在数据库上调用updateTask::whereIn('id', $taskIds)->update()

嗨,杰森,我不明白你第二段的意思:“您可以在请求正文中传递多个资源”。此外,我已编辑了上面的帖子以反映您的建议。如果您能看一下会很好,因为我没有解析任何请求数据来使用foreach循环来持久化数据。此外,我觉得我的问题没有得到解答,关于如何解决对像这样的URL发出http请求:http://localhost:8000/api/tasks/12,2,4,5 - LoveAndHappiness
1
我选择了一种解决方案,向我的API添加了两个额外的端点,“complete-all”和“clear-completed”,我通过一个简单的POST请求访问它们。然后我让后端处理工作(例如完成任务)。你认为这是正确的方法吗?我有点觉得这个解决方案很奇怪,因为我实际上没有通过请求将任何任务数据传递到服务器。我只是在服务器上执行一些代码。你认为这完全没问题,因为我甚至没有使用你提到的$taskIds。 - LoveAndHappiness
我理解这种感觉,但我认为没问题。唯一需要考虑的特殊情况是任务是否可以并发创建。如果是这样的话,在完成所有任务时你可以同时完成一个新任务。 - Jason McCreary
虽然我对这个解决方案不太满意,但我将您的答案标记为正确。感谢您的帮助。 - LoveAndHappiness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接