简体   繁体   中英

Laravel - Routes: Controller nested controller

My routes:

Route::apiResource('courses', 'CourseController');
Route::apiResource('courses.classrooms', 'ClassroomController');

List: php artisan route:list

api/v1/courses/{course}
api/v1/courses/{course}/classrooms/{classroom}

My question is: all my functions in classroom controller needs the course , something like that

public function index($course_id)
{
  $classroom = Classroom::where('course_id', $course_id)->get();
  return $classroom;
}

public function store($course_id, Request $request)
{
// ...
  $classroom->course_id = $course_id;
// ...
}

public function show($course_id, $id)
{
  $classroom = Classroom::where('course_id', $course_id)->find($id);
  return $classroom;
}
// ...

Have some Policy/Helper in Laravel to accomplish this automatically?

I believe it's not necessary to add the property $course_id in all functions manually, what can I do?

You can use a group to enclose all your routes. Something like:

 Route::group(['prefix' => '{course}'], function () {

// you can place your routes here

});

So all the routes that exist in that group will already have the course value in the url path and you don't have to "rewrite it" for every route.

If that field is set by you for example an env variable then inside your RouteServiceProvider you can put the prefix you want in the mapApiRoutes function.

 protected function mapApiRoutes()
    {
        Route::prefix('/api/v1/courses/'.config('app.myVariable'))
             ->middleware('api')
             ->namespace($this->namespace)
             ->group(base_path('routes/api.php'));
    }

That way ALL your api endpoints will start with that prefix and you can have it in all the endpoints.

If the routes are registered correctly like you posted, your methods in the ClassroomsController should receive an additional parameter that's the course id fragment from the url.

For example if you request /api/v1/courses/1/classrooms route, the controller will receive the correct {course} parameter set to 1 as the first parameter.

You could then implement the index method of the ClassroomsController to use implicit model binding and get the Course instance with the given url id for the course.

To do so you have to type-hint the Course model for the first function's parameter and name the variable as the url fragment you want to use to retrive your model.

In your code example, you should do:

public function index(Course $course)
{
    return $course->classrooms;
}

Note: I assume you have a relationship between Course and Classroom models to retrive the classrooms from the course model instance

You can read more about that on the official documentation here

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