拉拉维尔从REST API检索数据

36

好的,我有以下情况:

我正在构建的系统从REST API中检索数据并将该数据保存到数据库中。 我想知道如何实现这个功能,并且在Laravel结构(控制器、模型等)的哪里才能处理这种行为? Laravel是否具有从外部源检索数据的内置机制?


14
剧透:被选中的答案完全误导人。跳到第二个回答,那个有更多的赞,来了解如何准确地检索数据 :) - igorsantos07
现在,即使这个也已经改变了@igorsantos07和这是首选方法 - Tiago Martins Peres
5个回答

44

编辑:Buzz 已经超过一年没有更新了,现在建议使用 Guzzle,请参考 Mohammed Safeer's 的回答。


我使用了Buzz package来进行API请求。
您可以通过将其添加到您的composer.json文件的require部分中来添加此包。
{
    require: {
        "kriswallsmith/buzz": "dev-master"
    }
}

然后运行 composer update 命令来安装它。

接着,在 Laravel 中,您可以将其包装在一个类中(例如存储库类),该类处理 API 请求并返回数据供应用程序使用。

<?php namespace My\App\Service;

class SomeApi {

    public function __construct($buzz)
    {
        $this->client = $buzz;
    }

    public function getAllWidgets()
    {
        $data = $this->client->get('http://api.example.com/all.json');
        // Do things with data, etc etc
    }

}

注意:这是伪代码。您需要创建一个适合自己需求的类,并进行任何想要/需要的高级依赖注入或代码架构。
正如@Netbulae所指出的,Repository可能会对您有所帮助。他链接的文章是一个很好的起点。该文章与您的代码唯一的区别在于,您不是使用Eloquent模型从数据库获取数据,而是发出API请求并将结果转换为一组应用程序可以使用的数组/对象(基本上,只是数据存储不同,这是首先考虑使用存储库类的好处之一)。

14
我不明白为什么选择了其他答案作为正确答案。毫无疑问,这个问题是关于查询远程RESTful API而不是建立API的。 - alexleonard
被标记为正确的答案展示了如何构建一个应用和保护它以使用API和保存检索到的数据,因此它回答了问题并超出了其范围,但是以一种非常具体的方式。然而,我也更喜欢fideloper的答案,因为它更加通用(即使有具体的包推荐!)。 - petercoles
1
问题是“[...]从REST API检索数据[...] Laravel是否有内置机制从外部源检索数据?”这让我想到它是在问如何从Laravel应用程序调用其他Web服务。但是被接受的答案从另一方面描述了它 - 如何使用curl从Laravel应用程序检索数据。还有一个注意事项 - 不要盲目运行composer update - 它会更新所有库,可能会破坏某些内容。如果您想保持稳定,请始终使用composer require vendor/library方法。 - JustAMartin
2
Buzz似乎已经被放弃了。也许你应该使用Guzzle代替。 - rap-2-h

34

我们可以在Laravel中使用Guzzle包,它是一个PHP HTTP客户端,用于发送HTTP请求。

您可以通过composer安装Guzzle。

composer require guzzlehttp/guzzle:~6.0

或者,您可以在项目的现有composer.json中将Guzzle指定为依赖项

{
   "require": {
      "guzzlehttp/guzzle": "~6.0"
   }
}

以下是使用Guzzle在Laravel 5中的示例代码:

use GuzzleHttp\Client;
class yourController extends Controller {

    public function saveApiData()
    {
        $client = new Client();
        $res = $client->request('POST', 'https://url_to_the_api', [
            'form_params' => [
                'client_id' => 'test_id',
                'secret' => 'test_secret',
            ]
        ]);

        $result= $res->getBody();
        dd($result);

}

3
即使 Laravel 文档建议在项目中使用 Mandrill 或 Mailgun API 时使用 Guzzle,而 Guzzle 易于使用和安装。 - dollar

9

您可以选择使用什么:

  1. Guzzle
  2. CURL
  3. file_get_contents :

    $json = json_decode(file_get_contents('http://host.com/api/v1/users/1'), true);
    

Referrer


9

首先您需要在app/routes.php中创建路由。

/*
    API Routes
*/

Route::group(array('prefix' => 'api/v1', 'before' => 'auth.basic'), function()
{
    Route::resource('pages', 'PagesController', array('only' => array('index', 'store', 'show', 'update', 'destroy')));
    Route::resource('users', 'UsersController');
});
注意:如果您的API调用不需要身份验证,您可以删除'before' => 'auth.basic' 在这里,您可以从您的PagesController访问index, store, show, update和destroy方法。
请求URL将是:
GET http://localhost/project/api/v1/pages // this will call index function
POST http://localhost/project/api/v1/pages // this will call store function
GET http://localhost/project/api/v1/pages/1 // this will call show method with 1 as arg
PUT http://localhost/project/api/v1/pages/1 // this will call update with 1 as arg
DELETE http://localhost/project/api/v1/pages/1 // this will call destroy with 1 as arg

命令行CURL请求将如下(这里的用户名和密码是admin),并假设您有一个.htaccess文件,可以从URL中删除index.php

curl --user admin:admin localhost/project/api/v1/pages    
curl --user admin:admin -d 'title=sample&slug=abc' localhost/project/api/v1/pages
curl --user admin:admin localhost/project/api/v1/pages/2
curl -i -X PUT --user admin:admin -d 'title=Updated Title' localhost/project/api/v1/pages/2
curl -i -X DELETE --user admin:admin localhost/project/api/v1/pages/1

接下来,你的app/controllers文件夹中有两个控制器,它们的名称分别为PagesController.phpUsersController.php
其中,PagesController.php控制器用于处理关于网站页面的请求。
<?php


class PagesController extends BaseController {


    /**
     * Display a listing of the resource.
     *
     * @return Response
     * curl --user admin:admin localhost/project/api/v1/pages
     */

    public function index() {

        $pages = Page::all();;

        return Response::json(array(
            'status' => 'success',
            'pages' => $pages->toArray()),
            200
        );
    }


    /**
     * Store a newly created resource in storage.
     *
     * @return Response
     * curl --user admin:admin -d 'title=sample&slug=abc' localhost/project/api/v1/pages
     */

    public function store() {

        // add some validation also
        $input = Input::all();

        $page = new Page;

        if ( $input['title'] ) {
            $page->title =$input['title'];
        }
        if ( $input['slug'] ) {
            $page->slug =$input['slug'];
        }

        $page->save();

        return Response::json(array(
            'error' => false,
            'pages' => $page->toArray()),
            200
        );
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     * curl --user admin:admin localhost/project/api/v1/pages/2
     */

    public function show($id) {

        $page = Page::where('id', $id)
                    ->take(1)
                    ->get();

        return Response::json(array(
            'status' => 'success',
            'pages' => $page->toArray()),
            200
        );
    }


    /**
     * Update the specified resource in storage.
     *
     * @param  int  $id
     * @return Response
     * curl -i -X PUT --user admin:admin -d 'title=Updated Title' localhost/project/api/v1/pages/2
     */

    public function update($id) {

        $input = Input::all();

        $page = Page::find($id);

        if ( $input['title'] ) {
            $page->title =$input['title'];
        }
        if ( $input['slug'] ) {
            $page->slug =$input['slug'];
        }

        $page->save();

        return Response::json(array(
            'error' => false,
            'message' => 'Page Updated'),
            200
        );
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     * curl -i -X DELETE --user admin:admin localhost/project/api/v1/pages/1
     */

    public function destroy($id) {
        $page = Page::find($id);

        $page->delete();

        return Response::json(array(
            'error' => false,
            'message' => 'Page Deleted'),
            200
        );
    }

}

然后你有一个名为Page的模型,它将使用名为pages的表。

<?php

class Page extends Eloquent {
}

您可以使用Laravel4生成器通过php artisan generator命令创建这些资源。在此处阅读:这里
因此,使用此路由分组,您可以使用同一应用程序进行API请求和前端操作。

如果想将一个json数组作为参数传递给“update()”函数,并保存该数组中的所有字段,而不是一个一个地指定,应该如何操作呢?例如:$page->title =$input['title'];$page->slug =$input['slug'];等等。 - errakeshpd
@brito 简单的解决方案是 foreach ($input as $key => $value) { $page->$key = $value; } 可能有效。 - Anshad Vattapoyil
3
这是 OP 提出的问题吗?看起来他问的是关于「检索」的,而你回答了有关创建 API 的内容。 - igorsantos07
@igorsantos07 尝试解释完整的步骤,包括检索。 - Anshad Vattapoyil
4
我没有看到关于如何创建从API检索数据的模型的信息。您的回答都是关于创建API和利用Laravel资源控制器,这不是被问到的内容。 - igorsantos07

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接