Larvel:如何避免内部api调用中的json

Larvel:如何避免内部api调用中的json,api,request,format,laravel-4,response,Api,Request,Format,Laravel 4,Response,Laravel 4:在使用您自己的api的上下文中,我的XyzController使用我的自定义InternalApispatcher类创建一个请求对象,将其推送到堆栈(per)上,然后调度路由: class InternalApiDispatcher { // ... public function dispatch($resource, $method) { $this->request = \Request::create($this->apiBaseUrl . '/

Laravel 4:在使用您自己的api的上下文中,我的XyzController使用我的自定义InternalApispatcher类创建一个请求对象,将其推送到堆栈(per)上,然后调度路由:

class  InternalApiDispatcher {
// ...
public function dispatch($resource, $method)
{
    $this->request = \Request::create($this->apiBaseUrl . '/' . $resource, $method);
    $this->addRequestToStack($this->request);

    return \Route::dispatch($this->request);
}  
首先,我正在为一个集合开发一个基本的GET,并且希望响应内容的格式是一个雄辩的模型,或者任何准备好传递给视图的格式(可能是一个存储库之类的东西,稍后我会更高级)。让框架创建一个json响应,然后将其解码回其他内容以在视图中显示,这似乎效率低下。什么是一种简单/高效/优雅的方式来引导请求以我希望的格式返回响应,无论我在代码中的什么位置

另外,我已经看了很多,虽然我在BaseController中处理查询字符串的东西(多亏了),但这一切似乎变得太复杂了,我觉得我在树中迷失了方向

编辑:以下内容是否相关(来源)

通过在控制器上指定layout属性,指定的视图将为您创建,并且将是从操作返回的假定响应


如果您愿意,可以随意将其标记为OT,但我建议您可以从不同的角度重新考虑您的问题

如果您正在“使用您自己的API”,它是通过HTTP交付的,那么您应该坚持使用这种方法

尽管这看起来很奇怪,但好处是您可以将应用程序的这一部分完全替换为其他服务器。你可以在不同的盒子上运行应用程序的不同部分,你可以完全重写HTTP部分,等等。所有这些都是“网络规模”的好处

您要走的路线是连接发布者和订阅者。现在,因为他们都是你,或者更准确地说是你的单一应用,这不一定是件坏事。但是,如果您希望能够访问自己的“东西”,而不必求助于HTTP(或者至少是类似HTTP的)请求,那么我就不会费心伪造它。您最好定义一个不同的内部非web服务API,并调用它

该服务可能是“WebAPI”的基础,事实上,整个HTTP部分可能是核心服务之上相当薄的控制器层


它离您现在的位置不到一百万英里远,但与其使用用于输出HTTP请求的东西并将其弄脏,不如制作一些可以输出对象的东西,并将其包装为HTTP。

以下是我如何解决这个问题的,这样就不会对我的API的内部请求进行json编码或解码。此解决方案还演示了在API层上使用路由模型绑定,以及API层使用存储库。这一切对我来说都很好

路线:

Route::get('user/{id}/thing', array(
    'uses' => 'path\to\Namespace\UserController@thing',
    'as' => 'user.thing'));
//...
Route::group(['prefix' => 'api/v1'], function() 
{
    Route::model('thing', 'Namespace\Thing');
    Route::model('user', 'Namespace\User'); 

    Route::get('user/{user}/thing', [
    'uses' => 'path\to\api\Namespace\UserController@thing',
    'as' => 'api.user.thing']);
//...
控制器:

UI: UserController@thing
public function thing()
{
    $data = $this->dispatcher->dispatch('GET', “api/v1/user/1/thing”)
        ->getOriginalContent();  // dispatcher also sets config flag...
    // use $data in a view;
}
API:UserController@thing

public function thing($user)
{
    $rspns = $this->repo->thing($user);

    if ($this->isInternalCall()) { // refs config flag 
        return $rspns;
    }
    return Response::json([
    'error' => false,
    'thing' => $rspns->toArray()
], 200);
回购:


下面是我如何在Laravel 5.1中实现它的。它需要对控制器进行一些基本的更改才能工作

不要使用
return response()->make($data)
输出响应,而是执行
return$data

这允许使用
App::make('apicontroller')->methodname()
从其他控制器调用控制器方法。返回的是对象/数组,而不是JSON

要处理外部API,现有路由保持不变。您可能需要一个中间件来对响应进行一些处理。下面是一个基本示例,其中camel对JSON的键名进行了装箱

<?php
namespace App\Http\Middleware;
use Closure;
class ResponseFormer
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if($response->headers->get('content-type') == 'application/json')
        {
            if (is_array($response->original)) {
                $response->setContent(camelCaseKeys($response->original));
            }
            else if (is_object($response->original)) {
                //laravel orm returns objects, it is a huge time saver to handle the case here
                $response->setContent(camelCaseKeys($response->original->toArray()));
            }
        }
        return $response;
    }
}

这就是我所需要的那种全局性的帮助。虽然我用配置标志解决了我最初的问题,但总体结构似乎是错误的。但我看看我现在有没有。app dir中的ctrlr、模型、视图等将管理我的app的UI,它仍然可以有RESTful URL,这些ctrlr可以调用内部服务api,它将有匹配的RESTful URL,并且可以作为单独web api的基础。但现在我发现自己身处一片名称空间的灌木丛中。你能给我一个合适的目录结构的草图吗?谢谢
<?php
namespace App\Http\Middleware;
use Closure;
class ResponseFormer
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if($response->headers->get('content-type') == 'application/json')
        {
            if (is_array($response->original)) {
                $response->setContent(camelCaseKeys($response->original));
            }
            else if (is_object($response->original)) {
                //laravel orm returns objects, it is a huge time saver to handle the case here
                $response->setContent(camelCaseKeys($response->original->toArray()));
            }
        }
        return $response;
    }
}