Правилен начин за влагане на контролери за динамични ресурси с Laravel при създаване на REST API

Намерих добра информация за работа с вложени контролери на ресурси и предаване на множество ограничения, но изглежда не намирам нищо за този конкретен проблем (вероятно защото мисля за всичко погрешно!).

Ако искам да създам следното в моя API

  • /коли (покажи всички коли)
  • /автомобили/1 (покажи carId = 1)
  • /cars/1/performance (покажи ефективността за carId=1)
  • /cars/1/performance/parts (показва производителността на частите за carId=1)
  • /cars/1/performance/parts/1 (показва ефективността на partId=1 за carId=1)
  • /автомобили/производителност (показва ефективността на всички автомобили)
  • /автомобили/производителност/части
  • /части
  • /части/1 и т.н... (същото за частите като автомобилите по-горе)

ще трябва ли да създам маршрути и контролери за повечето от тях по този начин

Route::group(array('prefix' => 'myAwesomeCarApi'), function()
{
    Route::resource('cars', 'CarsController'); 
    Route::resource('cars/performance', 'CarsPerController');
    Route::resource('cars/performance/parts', 'CarsPerPartsController');
    Route::resource('cars.performance/parts', 'CarsPerPartsController');
    Route::resource('parts', 'PartsController');
    Route::resource('parts/performance', 'PartsPerController');
    etc...
});

или има някакъв трик, който ми липсва за създаване на динамични контролери, например само 3 (CarController, PartsController, PerformanceController) и обработка на различните маршрути в кода?


person Nick    schedule 25.03.2015    source източник


Отговори (1)


Мисля, че това, което търсите, са вложени контролери на ресурси. Те ви позволяват да създавате маршрути като /car/1/part/1. Този маршрут ще се съпостави с действието CarPartController@show и ще предаде два параметъра: ID на колата и ID на частта.

По отношение на производителността на автомобилите/частите, бих казал, че това е нещо като метода „покажи“ (в това изпълнение не е само по себе си), така че ще създаде друг метод във вашите контролери като този:

class CarPartController extends Controller {

    public function show($carId, $partId)
    {
        // Show specified part for specified car
    }

    public function performance($carId, $partId)
    {
        // Show the performance for specified part on specified car
    }

}

Тогава вашите маршрути ще изглеждат така:

Route::get('car/{car}/performance', 'CarController@performance');
Route::get('car/{car}/part/{part}/performance', 'CarPartController@performance');

Route::resource('car', 'CarController');
Route::resource('car/{car}/part', 'CarPartController');

Според документацията на Laravel нересурсните методи трябва да бъдат дефинирани преди ресурсните контролери.

Можете също така да направите този подход една крачка напред и да приложите обвързване на модела на маршрута, така че екземплярите на вашия Car и Part модел да бъдат инжектирани в действията на вашия контролер, а не в идентификаторите:

Route::model('car', 'Car');
Route::model('part', 'Part');

И примерно действие на контролера:

public function performance(Car $car, Part $part)
{
    // Show performance for specified part on specified car
}

Надявам се това да помогне.

person Martin Bean    schedule 25.03.2015
comment
Благодаря, това е страхотно, точно от това имах нужда. Когато за първи път започвате да използвате routes, mvc и REST api, има много концепции, с които да се ориентирате, така че прилагането им понякога може да бъде объркващо! - person Nick; 25.03.2015
comment
Предполагам, че последващият ми въпрос е как или дали това се вписва в принципите на REST, защото след като започна да използвам Route::get('car/{car}/performance', 'CarController@performance'); не се ли отдалечавам от стриктните принципи GET/PUT/DELETE и т.н. REST - person Nick; 25.03.2015
comment
Начинът, по който разбрах вашето приложение, крайните точки performance просто събираха статистически данни и ги връщаха, вместо да бъдат самостоятелна единица, която може да бъде актуализирана, изтрита и т.н. Това правилно ли е? - person Martin Bean; 25.03.2015
comment
Да точно. Мисля, че просто продължавам да се опитвам да мисля за производителността като за обект, който може да се контролира с помощта на CRUD, когато всичко това е просто повече функционалност, добавена към контролерите за автомобили и части за получаване на съпоставени данни. (Предполагам, че мислите за данните като за живи от кола, която ги събира, никога не трябва да се променят) - person Nick; 26.03.2015
comment
Наздраве Мартин, това наистина ми помогна! - person Nick; 26.03.2015
comment
Няма проблем. Уведомете ме, ако имате други въпроси и ще направя всичко възможно, за да им отговоря. - person Martin Bean; 26.03.2015
comment
Не е необходимо да добавяте сегмента, който съдържа заместващия знак, можете да го напишете така: Route::resource('car.part', 'CarPartController'); - person cdarken; 12.08.2016
comment
@cdarken Какъв е вашият коментар във връзка с? Няма ли сегмент, който съдържа заместващ знак? - person Martin Bean; 12.08.2016
comment
Имах предвид това: Route::resource('car/{car}/part', 'CarPartController');. Можете да пропуснете частта {car} и просто да я напишете като car.part - person cdarken; 15.08.2016
comment
@cdarken Това не е заместващ знак. Това е параметър на маршрута. - person Martin Bean; 16.08.2016
comment
@MartinBean прав си. И този параметър ще се генерира автоматично, ако използвате точката. - person cdarken; 17.08.2016
comment
Просто сигурен последващ въпрос. Трябва ли да създадете различен PartController за всички CRUD действия и да използвате само CarPartController като крайна точка за показване? Ще следвам същия подход с Posts и Comments и си мисля кое би било по-подходящо. Дали comment CRUD действията в PostCommentController или имат отделно като CommentController? - person LefterisL; 11.10.2016
comment
@TerisL Това наистина зависи от всеки отделен случай, тъй като няма твърдо и бързо правило. За коментари вероятно бих му дал собствен контролер (въпреки че коментарът ще принадлежи на публикация). За CRUD-ing на автомобилни части бих избрал това, което би имало най-голям смисъл за потребителя. Потребителят ще навигира ли до част, като първо мине през автомобил? Ако е така, бих създал вложен контролер на ресурси в този случай. - person Martin Bean; 11.10.2016