根据客户端发送HTML或JSON响应

时间:2015-09-03 18:33:07

标签: php rest laravel laravel-5

我有一个带有Eloquent实体的Laravel应用程序及其各自的RESTful resource controllers,如下所示:

模型

x

控制器

class Entity extends Eloquent {
    ...
}

现在我正在构建一个Android应用程序,而不是返回视图,我需要数据作为JSON。

在我目前的解决方案中,对于我从Android应用程序发出的每个请求,我都添加了一个获取查询参数class EntityContoller { public function index() { Entity $entities = Entity::all(); return view('entity.index', compact($entities)); } ... // And many more routes like that } 。我在控制器中检测到,并按如下方式相应地发送数据。但这似乎很乏味,我必须在任何地方写出相同的条件。

contentType=JSON

我可以做到这一点的最佳方式是什么,而不必在每个控制器操作中都写出这个条件?

3 个答案:

答案 0 :(得分:5)

如果您不想更改控制器,那么您可以使用middleware来改变之后的响应 从控制器返回。

中间件会收到控制器的响应,检查contentType == JSON然后返回正确的响应。

中间件看起来像这样:

use Closure;
class JsonMiddleware {
    public function handle($request, Closure $next) {
        // Get the response from the controller
        $response = $next($request);

        // Return JSON if necessary
        if ($request->input('contentType') == 'JSON') {
            // If you want to return some specific JSON response
            // when there are errors, do that here.

            // If response is a view, extract the data and return it as JSON
            if (is_a($response, \Illuminate\View\View::class)) {
                return response()->json($response->getData());
            }
        }

        return $response;
    }
}

然后,您可以在app/Http/Kernel.php中注册中间件,方法是将其附加到$routeMiddleware数组。

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    // New Middleware
    'json' => \App\Http\Middleware\JsonMiddleware::class,
];

然后,您只需将中间件分配给可能返回JSON的路由。

Route::get('user/{user_id}', ['middleware' => 'json', 'uses' => 'App\UserController@getUser']);

您可以阅读有关中间件here以及注册和分配中间件here的更多信息。

您可以阅读有关在Laravel here中发送JSON响应的信息。

答案 1 :(得分:1)

自定义响应类怎么样?让我给你一个想法。创建一个新的类或服务:

class ResourceResponse{

    public function __construct($request, $object, $view = null){
        // setting values
    }

    public function __toString(){
        if ($this->request->get('contentType') == 'JSON'){
            return $this->object;
        }

        // view as fallback
        return view($this->view, compact($this->object));
    }
}

然后在您的资源中,如果未指定json类型,则只需使用视图名称作为后备调用函数:

public function index(Request $request) {
    $entities = Entity::all();
    return new ResourceResponse($request, $entities, 'entity.index'); 
}

如果您非常确定响应应该是JSON格式,那么您可以忘记视图名称:

public function index(Request $request) {
    $entities = Entity::all();
    return new ResourceResponse($request, $entities); 
}
  $request方法的

index()参数使用Laravel 5's docs

中所述的类型提示

答案 2 :(得分:0)

首先使用受保护的函数createView

创建BaseController
Select * FROM grids 
WHERE g_date_created + interval 3 day BETWEEN timestamp_1 AND timestamp_2

然后在每个控制器中扩展此基本控制器

class BaseController extends Controller
{
    protected function createView($object)
    {
        if (Request::get('contentType', 'JSON')) return $object;
        return view('entity.index', compact($object));
    }
}

如果还有其他任何异常,例如多个对象或错误,则无法单独处理它。