I have this Many to Many relationship between Courses and Programs. I can insert new courses and add as many programs as I want and it's returning correctly. The problem is on Update. I can fecth all data in my Course update form and all Programs that was selected through checkboxes checked or unchecked.
My idea is when I update the Course, I want to delete all Programs related (detach()) and attach again according to Programs checked in the update form.
The problem happens when I call the update method and it calls the detach().
My models are:
Course (model):
class Course extends Model
{
protected $fillable = [
'name', 'title', 'description', 'is_active'
];
public function programs(){
return $this->belongsToMany(Program::class)->withTimestamps();
}
}
Program (model):
class Program extends Model
{
protected $fillable = [
'name', 'description', 'is_active'
];
public function courses(){
return $this->belongsToMany(Course::class)->withTimestamps();
}
}
My update on CoursesController:
public function update(Request $request, $id)
{
$request->validate([
'name' => 'required',
'title' => 'required'
]);
// $course = Course::whereId($id)->update($request->all());
$course = Course::whereId($id)->update([
'name' => $request->name,
'title' => $request->title,
'description' => $request->description,
'is_active' => $request->is_active
]);
$course->programs()->detach();
$program = Program::find($request->programs);
$course->programs()->attach($program);
return response()->json([
'course' => $course,
'message' => 'Course has been Updated!'
]);
}
my Course Vuejs component:
<template>
...
</template>
<script>
export default {
data(){
return {
course:{
name: '',
title: '',
description: '',
is_active: true,
programs: []
},
courses: [],
uri: 'http://127.0.0.1:8000/courses/',
errors: [],
new_update_course: [],
toastr: toastr.options = {"positionClass": "toast-top-full-width"},
programs: [],
uriPrograms: 'http://127.0.0.1:8000/activePrograms/',
}
},
methods: {
...
loadUpdateCourseModal(index){
this.errors = [];
$("#update-course-modal").modal("show");
this.new_update_course = this.courses[index];
this.new_update_course.programs.forEach(program => {
this.new_update_course.programs.push(program.id)
});
},
...
updateCourse(){
axios.patch(this.uri + this.new_update_course.id, {
name: this.new_update_course.name,
title: this.new_update_course.title,
description: this.new_update_course.description,
is_active: this.new_update_course.is_active,
programs: this.new_update_course.programs
}).then(response =>{
$("#update-course-modal").modal("hide");
toastr.success(response.data.message);
}).catch(error=>{
if(error.response.data.errors.name){
this.errors.push(error.response.data.errors.name[0]);
}
if(error.response.data.errors.title){
this.errors.push(error.response.data.errors.title[0]);
}
if(error.response.data.errors.description){
this.errors.push(error.response.data.errors.description[0]);
}
});
},
...
},
mounted(){
...
}
}
</script>
If I try to update the course with id = 2, for example, in my laravel log, the error is:
local.ERROR: Call to a member function programs() on integer {"userId":1,"exception":"[object] (Symfony\Component\Debug\Exception\FatalThrowableError(code: 0): Call to a member function programs() on integer at /Users/GiselleTavares/Documents/.../app/Http/Controllers/CoursesController.php:120) [stacktrace]
0 [internal function]: App\Http\Controllers\CoursesController->update(Object(Illuminate\Http\Request), '2')
The line for CoursesController.php:120 is:
$course->programs()->detach();
I don't understand what this error means...
Call to a member function programs() on integer ...
If I comment these 3 lines below, I can update the course data but, of course, without changes on Programs relationship...
$course->programs()->detach();
$program = Program::find($request->programs);
$course->programs()->attach($program);
If I comment just the detach() line, the attach() line show the same error above. However, I use exactly the same (without the detach()) on my store() and it's working.
Any ideas? I tried to find solutions but nothing helped...