简体   繁体   中英

Laravel 5: Updating Multiple Records

I have a Simple Todo App , that doesn't persist the update of multiple records at once. The client version works properly here: http://codepen.io/anon/pen/bVVpyN

Everytime I make an action, I fire a http request to my laravel API to persist the data. But I have trouble with my completeAll method .

Whenever I click the Complete All button, I execute the completeAll method :

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 });
},

Here I send a request to an URL that might look like this:

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

And together with it, I send the tasks object . This is the request payload from chrome developer tools:

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

Then on the serverside I have an update function in my TasksController that looks like this:

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';
}

The above $tasks and $newTasks variable var_dump the same, because I use the toArray() method on the $tasks variable.

But when I try to update the tasks I get this error:

preg_replace(): Parameter mismatch, pattern is a string while replacement is an array

Not sure why. Since in my understanding Task::whereIn('id', $taskIds) is an object and not a string.

Alternative routes that I tried so far

  1. Using a foreach/for loop, to loop through the $tasks array, which I couldn't make to work, because I had also to loop through the $newTasks array to assign them, like this:

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

  2. Creating another endpoint on my API to just complete every task, to an URL like this:

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

And then executing a completeAll method on my TasksController, where I set each task to completed. But I couldn't make it work, because I got a

Method not allowed exception

Not sure why, but I figured it is better to use my original method with an API like this:

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

Because it was suggested here: https://laracasts.com/discuss/channels/code-review/vuejs-delete-multiple-tasks-each-task-one-request


Please advice on my original attempt to help me make this simple TodoApp work.

Alternatively, if it is for the better, please help me make the foreach/for loop work. Thanks.


EDIT

According to an answer, it was suggested to follow point 2 from above and create an additional endpoint.

These are my routes:

在此输入图像描述

I use a post method to the url:

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

Executed from my app.js throught this:

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

And this is my adapted 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']);
}

The app persists the data now correctly, but it troubles me, that I am not really updating anything from the clientside. I am just executing serverside code, because I am not really passing any query.

How would I solve the problem, using an URL like this:

http://localhost:8000/api/tasks/1,23,43,5

Thanks

Laravel CRUD methods expect on a single resource. As such, sending several resources to update at does not follow this requirement.

While you could update the update method, I would encourage you to create a completeTasks or completeAll method that operates on several resources. You could pass multiple resources in the request body.

To do this, you need to:

  • Add a Route
  • Parse the request data for Todo ids (like you for loop)
  • Call update on the database ( Task::whereIn('id', $taskIds)->update() )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM