基于 Laravel + Vue 构建 API 驱动的前后端分离应用系列(七) —— 实现 Laravel 后端 API 接口

上一篇教程中,我们通过 Vue Router 为 Roast 应用添加了前端路由,现在我们需要为对应的页面提供数据以便渲染。需要注意的是,在 API 驱动的单页面应用中,所有数据都是通过 Ajax 异步加载的,因此,我们需要现在 Laravel 后端提供 API 接口,然后根据接口返回数据通过 Vue 进行渲染。

第一步:设计路由

在提供 API 接口之前,需要先明确提供哪些路由,在上一篇教程中,我们在前端定义了这些关于咖啡店的路由:

  • /cafes
  • /cafes/new
  • /cafes/:id

在 Laravel 后端,我们要为这些前端路由定义相应的后端独立 API 接口。

/cafes 路由中,我们需要获取系统的咖啡店列表;/cafes/new 路由在前端是一个 GET 请求(显示提交表单),但是 API 端将是一个 POST 请求,用于添加咖啡店;/cafes/:id 路由用于加载某个咖啡店的信息。

第二步:添加路由到 routes/api.php

明确要提供的 API 路由之后,首先打开 routes/api.php 文件,该文件包含应用的所有 API 路由,我们也将在这里定义我们的 API 路由,在 Laravel Passport 配置教程中,我们为所有 API 路由添加了 v1 前缀,以方便后续支持多版本 API 扩展。

首先添加 cafes 路由:

Route::get('/cafes', 'API\CafesController@getCafes');

我们还没有构建 CafesController 控制器,但是很快就会创建。

然后,添加一个 POST 路由:

Route::post('/cafes', 'API\CafesController@postNewCafe');

该路由用于处理前端通过表单提交过来的咖啡店。

最后,我们还需要一个获取咖啡店详情的路由:

Route::get('/cafes/{id}', 'API\CafesController@getCafe');

添加完以上三个路由后,现在 routes/api.php 文件内容如下:

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::group(['prefix' => 'v1', 'middleware' => 'auth:api'], function(){
    Route::get('/user', function( Request $request ){
        return $request->user();
    });

    /*
     |-------------------------------------------------------------------------------
     | Get All Cafes
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes
     | Controller:     API\CafesController@getCafes
     | Method:         GET
     | Description:    Gets all of the cafes in the application
    */
    Route::get('/cafes', 'API\CafesController@getCafes');

    /*
     |-------------------------------------------------------------------------------
     | Get An Individual Cafe
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes/{id}
     | Controller:     API\CafesController@getCafe
     | Method:         GET
     | Description:    Gets an individual cafe
    */
    Route::get('/cafes/{id}', 'API\CafesController@getCafe');

    /*
     |-------------------------------------------------------------------------------
     | Adds a New Cafe
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes
     | Controller:     API\CafesController@postNewCafe
     | Method:         POST
     | Description:    Adds a new cafe to the application
    */
    Route::post('/cafes', 'API\CafesController@postNewCafe');
});

第三步:构建控制器 API/CafesController.php

定义好路由之后,接下来需要创建 app/Http/Controllers/API/CafesController.php 控制器了:

<?php

namespace app\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Request;

class CafesController extends Controller
{

}

然后根据路由定义填充相应的控制器动作:

class CafesController extends Controller
{
    /*
     |-------------------------------------------------------------------------------
     | Get All Cafes
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes
     | Method:         GET
     | Description:    Gets all of the cafes in the application
    */
    public function getCafes(){

    }

    /*
     |-------------------------------------------------------------------------------
     | Get An Individual Cafe
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes/{id}
     | Method:         GET
     | Description:    Gets an individual cafe
     | Parameters:
     |   $id   -> ID of the cafe we are retrieving
    */
    public function getCafe($id){

    }

    /*
     |-------------------------------------------------------------------------------
     | Adds a New Cafe
     |-------------------------------------------------------------------------------
     | URL:            /api/v1/cafes
     | Method:         POST
     | Description:    Adds a new cafe to the application
    */
    public function postNewCafe(){

    }
}

目前所有方法都留空,留待后续创建完数据表和模型类后编写具体的实现代码。

第四步:构建模型类 Cafe.php

我们将通过 Eloquent ORM 来管理数据模型,所以需要创建咖啡店对应模型类。在项目根目录下通过如下 Artisan 命令来创建这个模型类:

php artisan make:model Models/Cafe -m 

该命令会将模型类 Cafe 创建到 app/Models 目录下,同时会在 databases/migrations 目录下创建对应的数据库迁移文件 {timestamp}_create_cafes_table

第五步:构建 Cafe 模型对应迁移文件

在上一步中,我们已经创建了数据库迁移文件,接下来我们需要编写该迁移文件定义要生成的数据表的数据结构,打开 create_cafes_table 文件,编辑 up() 方法如下:

public function up()
{
    Schema::create('cafes', function( Blueprint $table ){
        $table->increments('id');
        $table->string('name');
        $table->text('address');
        $table->string('city');
        $table->string('state');
        $table->string('zip');
        $table->decimal('latitude', 11, 8);
        $table->decimal('longitude', 11, 8);
        $table->timestamps();
    });
}

然后运行 php artisan migrate 命令创建这个数据表:

roast cafes表结构

第六步:完成 /api/v1/cafes 路由(GET)

模型类和数据表都已经定义好了,接下来就可以编写具体的业务逻辑代码了。

回到 app/Http/Controllers/API/CafesController.php 文件,在控制器顶部引入模型类:

use App\Models\Cafe;

首先编写 getCafes() 方法,目前该方法只是简单返回所有的咖啡店:

public function getCafes(){
    $cafes = Cafe::all();
    return response()->json($cafes);
}

我们将以 JSON 格式返回 API 请求数据,后面也都是这样。

第七步:完成 /api/v1/cafes/:id 路由

获取某个咖啡店的信息也很简单,编辑 getCafe($id) 方法如下:

public function getCafe($id){
    $cafe = Cafe::where('id', '=', $id)->first();
    return response()->json($cafe);
}

我们通过 ID 去 cafes 查询模型数据并将其返回。

第八步:完成 /app/v1/cafes 路由(POST)

相比前两个路由而言,这个路由对应的业务逻辑稍微复杂一点:首先我们需要验证用户提交数据是否有效,如果验证通过则将其保存到数据库,否则返回错误信息。

我们先来看下需要用户提交哪些字段的数据:

  • name - 咖啡店的名字
  • address - 咖啡店的详细地址
  • city - 咖啡店所在城市
  • state - 咖啡店所在的省份
  • zip - 邮政编码

cafes 表的其他字段都是动态添加的,无需用户手动提交。关于经度和纬度字段的获取,后续在地图 API 中会提到。

为了简化业务逻辑,我们假定用户提交的数据都是可靠的,将数据验证逻辑省略掉,只留下数据保存逻辑,所以编写 postNewCafe() 方法如下:

public function postNewCafe(){
    $cafe = new Cafe();

    $cafe->name     = Request::get('name');
    $cafe->address  = Request::get('address');
    $cafe->city     = Request::get('city');
    $cafe->state    = Request::get('state');
    $cafe->zip      = Request::get('zip');

    $cafe->save();

    return response()->json($cafe, 201);
}

创建成功后,我们将遵循 RESTful 原则返回 201 状态码,表示实体已创建。

至此,Laravel 后端 API 接口已经全部实现了,在下一篇教程中我们将在前端通过 Vue 发起异步请求来访问这些接口。

项目源码位于 Github 上:nonfu/roastapp

学院君 has written 1083 articles

Laravel学院院长,终身学习者

积分:137437 等级:P12 职业:手艺人 城市:杭州

4 条回复

  1. phper phper says:

    路由上边的注释是手敲的还是编辑器自动生成的?

  2. 会勇 会勇 says:

    简化代码:

    
    php artisan make:controller -r Api/CafesController
    
    ...
    
    Route::resource('cafes', 'CafesController');
    
    ...
    php artisan make:resource CafeResource
    

登录后才能进行评论,立即登录?