2.9. 内部调用

优质
小牛编辑
132浏览
2023-12-01

这个包的主要用途就是在 API 内部执行请求。它允许你在可用的 API 基础上构建你的应用。内部请求也可以返回原始数据,而不是原始响应对象,这意味着你可以获得与之相关的所有语法糖。

我们需要构建一个分发器实例来发起内部请求。

$dispatcher = app('Dingo\Api\Dispatcher');

我们现在可以用标准的 HTTP 进行内部请求.

Route::get('/', function () use ($dispatcher) {
    $users = $dispatcher->get('api/users');

    return View::make('index')->with('users', $users);
});

如果你在控制器中使用 Dingo\Api\Routing\Helpers 这个 trait ,可以用 $api 这个属性进行内部请求。

use Dingo\Api\Routing\Helpers;

class HomeController extends Controller
{
    use Helpers;

    public function index()
    {
        $users = $this->api->get('users');

        return view('index')->with('users', $users);
    }
}

发送数据

$dispatcher->with(['name' => 'Jason', 'location' => 'Australia'])->post('users');

或者你可以将数据作为第二个参数添加到 post 方法(也包括其他的 HTTP 动词,不只是 post

$dispatcher->post('users', ['name' => 'Jason', 'location' => 'Australia']);

指向特定的 API 版本

$dispatcher->version('v2')->get('users');

指向特定的域名

$dispatcher->on('api.example.com')->get('users');

上传附件

DingoAPI 支持多种上传附件的方法。 你可以传递一个 Symfony\Component\HttpFoundation\File\UploadedFile 实例数组, 当你向 API 上传附件时,这个非常方便。

$dispatcher->attach(Input::files())->post('photos');

或者你可以传递一个文件路径的数组,数组的 key 应该是文件的标识。

$dispatcher->attach(['photo' => 'photos/me.jpg'])->post('photos');

或者你可以传一个和文件路径相关的元数据数组。根据具体情况,这种方式会比上述方法会更准确,因为依赖包不需要运行计算 mime 类型和文件大小。

$dispatcher->attach([
    'photo' => [
        'path' => 'photos/me.jpg',
        'mime' => 'image/jpeg',
        'size' => '49430'
    ]
])->post('photos');

你也可以按需混合使用以上的这些方式。

发送 JSON 数据

$data = ['name' => 'bill', 'password' => 12345];

$dispatcher->json($data)->post('users');

如果 $data 是一个数组它将被自动编码。这个请求的 Content-Type 将被设置为 application/json

模拟认证用户

如果你的 API 端点需要认证,你可以在内部模拟一个给定的用户。例如,用户使用 Laravel 的身份验证登录到应用,你可以取得用户,然后模拟用户发起内部请求。

$dispatcher->be(auth()->user())->get('posts');

任何后续的请求都将被视为是同一用户。只是为给定的用户单个请求认证,你可以使用 once 方法。

$dispatcher->be(auth()->user())->once()->get('posts');

获取原始返回对象

所有的内部请求都会预先转换和格式化数据。例如,你可在内部接收到 API 从端点返回的一个 Eloquent 集合。 如果你需要返回原始对象,你只需要在调用方法前加上 raw 方法 。

$response = $dispatcher->raw()->get('users');

异常处理

在执行内部请求时,端点中抛出的任何异常都将被再次抛出,让你能够手动捕获。

public function store()
{
    throw new Symfony\Component\HttpKernel\Exception\ConflictHttpException('We got a conflict!');
}

如果想在内部调用上述端点,那么我们需要捕获抛出的异常。

try {
    app('Dingo\Api\Dispatcher')->with($payload)->post('users');
} catch (Symfony\Component\HttpKernel\Exception\ConflictHttpException $e) {
    // 在这里做点啥,比方返回一个错误
}

这个包在返回错误响应时会抛出 Dingo\Api\Exception\InternalHttpException异常,如果你使用 response 生成器构建返回错误,那么需要捕获这个异常。

public function show($id)
{
    return $this->response->errorNotFound('Could not find the user.');
}

当在内部调用时我们需要捕获这个异常。

try {
    app('Dingo\Api\Dispatcher')->get('users/1');
} catch (Dingo\Api\Exception\InternalHttpException $e) {
    //  我们可以在这里获取响应,检查错误码或响应主体
    $response = $e->getResponse();
}