Laravelapi自定义response格式

http路由

laravel的http路由文件有两个api.phpweb.php

1
2
3
4
5
6
7
8
9
➜  ~ ll /Users/shiwenyuan/test/test_demo/routes
total 32
drwxr-xr-x 6 shiwenyuan staff 192 10 9 12:19 ./
drwxr-xr-x 26 shiwenyuan staff 832 10 9 10:29 ../
-rw-r--r-- 1 shiwenyuan staff 572 10 9 12:19 api.php
-rw-r--r-- 1 shiwenyuan staff 508 10 9 10:28 channels.php
-rw-r--r-- 1 shiwenyuan staff 553 10 9 10:28 console.php
-rw-r--r-- 1 shiwenyuan staff 453 10 9 10:35 web.php
从命名上不难理解`web.php`为web服务的路由(用到了视图层),`api.php`则是做api服务(只负责返回数据)

传统写法

直接在app/Http/Controllers/Controller.php中添加实现,然后因为所有控制器都集成了Controller,所以就会有他的所有public方法,但是这么写个人感觉不够优雅,与laravel的核心思想背道而驰,所以我就把相关实现放到了Provider

创建response服务供应者

php artisan make:provider ResponseMacroServiceProvider

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
////该命令会在app/Providers目录下生成ResponseMacroServiceProvider
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ResponseMacroServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
}

/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
//初始文件格式如上

修改实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?php

namespace App\Providers;

use Carbon\Carbon;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Response;
use App\Library\Error;

class ResponseMacroServiceProvider extends ServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//error
Response::macro('fail', function ($err_code, $result=null, $msg='') {
if (is_null($result)){
$result = [];
}
if ($msg) {
$err_msg = $msg;
} else {
$err_msg = Error::errMsg($err_code);
}

$response_data = [
'code' => $err_code,
'message' => $err_msg,
'timestamp' => Carbon::now()->timestamp
];
app('log')->error(sprintf('params [%s] response [%s]',
json_encode(request()->all(), JSON_UNESCAPED_UNICODE),
json_encode($response_data, JSON_UNESCAPED_UNICODE)
));
return Response::json($response_data);
});
//正常返回
Response::macro('success', function ($result=null) {
if (is_null($result)){
$result = [];
}
$response_data = [
'code' => 100,
'content' => $result,
'timestamp' => Carbon::now()->timestamp
];
app('log')->debug(sprintf('params [%s] response [%s]',
json_encode(request()->all(), JSON_UNESCAPED_UNICODE),
json_encode($response_data, JSON_UNESCAPED_UNICODE)
));
return Response::json($response_data);
});
}
}

App\Library\Error的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php
/**
* Created by PhpStorm.
* User: shiwenyuan
* Date: 2019/10/9 13341007105@163.com
* Time: 15:13
*/
namespace App\Library;

class Error
{
public static function errMsg($code)
{
$maps = static::getErrs();

return isset($maps[$code]) ? $maps[$code] : '未知错误';
}

public static function getErrs()
{
return [
'500' => '服务器错误',
];
}
}

在全局服务提供者map中加入自己写的响应服务提供者

文件位置config/app.php

测试

增加测试路由

文件路径:routes/api.php

1
2
Route::get('test_success', 'IndexController@testSuccess');
Route::get('test_fail', 'IndexController@testFail');

增加测试实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

namespace App\Http\Controllers;

class IndexController extends Controller
{
public function testSuccess()
{
return response()->success(['username'=>'shiwenyuan']);
}
public function testFail()
{
return response()->fail(500);
}
}

最终结果

success

fail

日志记录

1
2
3
➜  ~ cat /Users/shiwenyuan/test/test_demo/storage/logs/laravel-2019-10-09.log
[2019-10-09 07:39:02] local.DEBUG: params [{"query":"index"}] response [{"code":100,"content":{"username":"shiwenyuan"},"timestamp":1570606742}]
[2019-10-09 07:39:05] local.ERROR: params [{"query":"index"}] response [{"code":500,"message":"服务器错误","timestamp":1570606745}]