0

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?

Thiago Valente
  • 673
  • 8
  • 25

2 Answers2

0

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.

pr1nc3
  • 8,108
  • 3
  • 23
  • 36
  • My routes make it automatically, the problem is because I need to get the property in all function of my classroom controller and I want an alternative [ policy / providers ] to get the course automatically. – Thiago Valente Aug 05 '19 at 11:23
  • Where is that course coming from? How you set it? Is it coming from the user like a request or is it environment based ? If it is coming as a request to group all your endpoints will solve your issue and you can access it like `$request->course`. If it is a field in your env file then i would follow the second approach. – pr1nc3 Aug 05 '19 at 11:24
  • When I put ``Route::apiResource('courses.classrooms', 'ClassroomController');`` Laravel make automatically ``api/v1/courses/{course}/classrooms/{classroom}``, that is to get my "classroom" need be related to course – Thiago Valente Aug 05 '19 at 11:28
0

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

mdexp
  • 3,492
  • 2
  • 9
  • 20
  • It’s working, but don’t solve my problem... I have relationship, this way I will still get the course, but this is necessary to do in all function... I want a automatically way to dont be necessary add in ```index(Course $course)```, ```show(Course $course)``` , ```update(Course $course)``` – Thiago Valente Aug 05 '19 at 13:12