我想制作一个适用于web的Laravel 5.1应用程序和适用于移动应用程序的api。我想为api请求返回json,为web浏览器返回view。目前,我设置了不同的路线和不同的控制器。在这种方法中,我重复代码。我不知道设计这个体系结构的最佳方法是什么。此外,我也浏览过一些类似的帖子,建议在网络浏览器中使用angular.js。
// web controller
Route::resource('product', 'ProductController');
// api controller
Route::group(['prefix' => 'api'], function() {
Route::resource('product', 'APIProductController');
});
您可以有两种基本方法:
- 保留单独的路由和控制器,但将所有公共控制器的代码移动到一个服务中。这可能是最干净、最灵活的解决方案,因为它可以很容易地在未来独立更新API和web方法
- 或者,您可以将api和web请求路由到同一个控制器,将Request对象传递到其中,然后根据某个请求属性决定返回哪个响应,json或html
例如,对于第二种方法,你可以这样做:
// web controller
Route::resource('product', 'ProductController');
// api controller
Route::group(['prefix' => 'api'], function() {
Route::resource('product', 'ProductController');
});
// and in the ProductController you have
public function index(Request $request)
{
// do some stuff...
if ($request->segment(1) === 'api') { // route prefix was api
// return json
} else {
// return the view
}
}
您也可以使用$request->wantsJson((方法检查Accept:
头,或者您可以在所有API调用中传递一个特殊的GET变量(例如?_format=json
(,以定义响应格式应为json,正如@Bogdan Kuštan已经建议的那样。IMHO如果你已经在url上使用了api前缀,那么只需检查一下就更可靠、更干净了。
一种方法是使用内容协商方法。您将传递头Accept: application/json
,然后您的应用程序将返回json格式的响应。然而,有些代理服务器不尊重内容协商,那么你的应用程序就会崩溃(你可以在这里阅读更多Drupal放弃内容协商的原因(。
另一种可能性是使用一些GET
变量来返回请求的格式,例如:/api/product?format=json
此外,您可以从/api
调用传递变量:
Route::get('/api/product', ['as' => 'product', function(){
return App::make('ProductController')->index('json');
}]);
public function index($format) {
// Your controller code
if ($format == 'json') {
// return JSON
}
// return HTML
}
或者,您可以直接解析URI,看看它是否以/API
开头(不推荐(。我的选择是内容协商或/和format
GET变量。