所以@Chris建议了一个专门的关系控制器,而@RossWilson有一种天才的方式来重新使用控制器来处理关系(至少对于加载Book
的行为)。
不幸流明的RouteProvider
返回一个简单的数组,因此不具有$request->route($param)
方便,更重要的是,$request->route()->forgetParameter($param)
。
===新的解决方案===
我落得这样做基本上为@RossWilson建议完全一样,只是在被流明支持的方式。我没有在控制器的__construct
中获得路由参数,而是创建了一个中间件,将路由参数移动到请求的输入和查询数组上。
中间件看起来是这样的:
public function handle($request, $next)
{
if ($genre_id = Arr::get($request->route()[2], 'genre')) {
// Add 'genre_id' to the input array (not replacing it if it already exists).
$request->merge(['genre_id' => $request->input('genre_id', $genre_id)]);
// Add 'genre_id' to the query array.
$request->query->add('genre_id', $genre_id);
// Forget the route parameter
// Has to be done manually, because Lumen...
$route = $request->route();
$request->setRouteProvider(function() use ($route) {
Arr::forget($route[2], 'genre');
return $route;
});
}
// Pass the updated $request to $next.
return $next($request);
}
我在执行我只能为GET
和DELETE
请求的查询参数,并输入参数POST
和PUT
。
然后,您可以重新使用BookController
作为genre.book
资源,从$request->query('genre_id')
过滤并关联$request->input('genre_id')
的关系。
===原液===
相反,我结束了一个与专用控制器的关系GenreBookController
,从非关系控制器BookController
继承。由于需要匹配的方法声明(请参阅下面的$book_id = null
以解决此问题),但它不够精美,但它非常纤薄而干燥。
GenreBookController extends BookController
:
protected function addGlobalScope($genre_id)
{
// Thanks Ross Wilson for the global scope suggestion.
Book::addGlobalScope('genreScope', function ($query) use ($genre_id) {
$query->where('genre_id', $genre_id);
});
}
public function show(Request $request, $genre_id, $book_id = null)
{
$this->addGlobalScope($genre_id);
return parent::show($request, $book_id);
}
和BookController的,展现的方法是照常营业(它并不需要知道有关show
额外参数)。
我也想出了一个简单的方式为GenreBookController
通过类型参数传递给store
方法:
public function store(Request $request, $genre_id)
{
// This way lets an input genre_id override the Route parameter.
$request->merge(['genre_id' => $request->input('genre_id', $genre_id)]);
// This way forces the Route parameter to be used over input parameters.
$request->merge(['genre_id' => $genre_id]);
return parent::store($request);
}
,并再次,为BookController
是企业像往常一样,当然它可能作出的任何通过$request->input('genre_id')
的流派的验证/授权。这样就没有重复的验证和授权逻辑。
了一份关于FormRequests
如果使用FormRequests验证genre_id
,确认发生的GenreBookController
才能从路由参数设置genre_id
输入变量。
当我看到它,你有两个选择:
- 使用中间件路线参数移动到请求输入。
- 把它放在你的
FormRequest
的authorize
方法中(我没有测试过,因为我不喜欢把这种逻辑放在这里)。
Laravel:如果你不使用流明,我建议考虑看看@ RossWilson的答案,这在我看来是一个小清洁。
您genre.books的输出是否与'books'相同,但是它的作用范围是'genre',或者您将包含其他信息。另外,你会想要从'genre.books'创建一个完整的资源吗?还是只是'index'和'show'方法? –
另外,您使用的是什么版本的Laravel? –
@RossWilson我正在使用Lumen/Laravel 5.4。我希望我想返回相同的结果,并且我喜欢使'store'和'update'方法一致的想法,但我不想结束太多不必要的复杂性。 – Zoon