Reputation: 10135
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
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]) } }
Creating another endpoint on my API to just complete every task, to an URL like this:
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
Upvotes: 4
Views: 3032
Reputation: 72971
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:
for
loop)update
on the database (Task::whereIn('id', $taskIds)->update()
)Upvotes: 2