Laravel API 開發教程 - 基礎篇

Laravel Api 開發基礎篇

準備工做

建立應用php

$ laravel new api-basic

建立數據庫mysql

> create database ApiBasic

配置 .envlaravel

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ApiBasic
DB_USERNAME=root    
DB_PASSWORD=123456

建立 Lesson 相關git

$ php artisan make:model Lesson -rm

編輯遷移github

/database/migrations/2017_06_03_052535_create_lessons_table.php
Schema::create('lessons', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title'); // 標題
    $table->text('body'); // 內容
    $table->boolean('free'); // 免費否
    $table->timestamps();
});

執行遷移sql

$ php artisan migrate

定義模型工廠數據庫

/database/factories/ModelFactory.php
$factory->define(App\Lesson::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'title' => $faker->sentence,
        'body'  => $faker->paragraph,
        'free'  => $faker->boolean(),
    ];
});

填充數據json

$ php artisan tinker
factory(\App\Lesson::class,50)->create();

基本的 Api 認證

定義路由api

/routes/api.php
Route::group(['prefix' => 'v1'], function() {
    Route::resource('lessons', 'LessonController');
});
  • api.php 中定義的路由會自動添加 api 前綴;app

  • 添加版本 v1 方便進行 api 版本管理;

數據的基本返回 - 取出數據,格式化,而後返回

/app/Http/Controllers/LessonController.php
use App\Lesson;

public function index()
{
    $lessons = Lesson::all();
    return response()->json([
        'status'      => 'success',
        'status_code' => 200,
        'data'        => $this->transforms($lessons->toArray()),
    ]);
}

public function show(Lesson $lesson)
{
    return response()->json([
        'status'      => 'success',
        'status_code' => 200,
        'data'        => $this->transform($lesson->toArray()),
    ]);
}

/**
 * 對多條數據進行格式化
 * @param  array  $lessons [description]
 * @return [type]          [description]
 */
private function transforms(array $lessons)
{
    return array_map([$this, 'transform'], $lessons);
}

/**
 * 對單條數據進行格式化
 * @param  array  $lesson [description]
 * @return [type]         [description]
 */
private function transform(array $lesson)
{
    return [
        'title'   => $lesson['title'],
        'content' => $lesson['body'],
        'is_free' => (bool)$lesson['free'],
    ];
}

測試

  • 訪問所有課程 - /api/v1/lessons

  • 訪問某一課程 - /api/v1/lessons/2

重構

接下來,考慮的是對上面代碼的重構與優化。

Transform Class

首先是數據的轉化部分,其餘模塊也須要用到該功能,所以能夠將其抽象出來:

  • 多條數據的轉化 - 不一樣模塊用法都相同,都是遍歷並每一條數據進行處理;

  • 單條數據的轉換 - 不一樣模塊可根據本身的需求定製;

所以,能夠使用 PHP 抽象類來實現,建立一個通用的 TransFormer

/app/TransFormer/Transformer.php
<?php

namespace App\Transformer;

abstract class Transformer
{   
    /**
     * 轉換多條數據
     * @param  {[type]} array $items        [description]
     * @return {[type]}       [description]
     */
    public function transforms(array $items)
    {
        return array_map([$this, 'transform'], $items);
    }

    abstract public function transform(array $item);
}

而後建立一個 LessonsTransform 來實現對 lessons 數據的轉化

/app/TransFormer/LessonsTransformer.php
<?php

namespace App\Transformer;

class LessonsTransform extends Transformer
{
    /**
     * [transform description]
     * @param  array  $lesson [description]
     * @return [type]         [description]
     */
      public function transform(array $lesson)
      {
          return [
            'title'   => $lesson['title'],
            'content' => $lesson['body'],
            'is_free' => (bool) $lesson['free'],
        ];
      }
}

控制器的方法,就能夠改爲

/app/Http/Controllers/LessonController.php
<?php

namespace App\Http\Controllers;

use App\Lesson;
use App\Transformer\LessonsTransform;
use Illuminate\Http\Request;

class LessonController extends Controller
{
    protected $lessonsTransform;
    public function __construct(LessonsTransform $lessonsTransform)
    {
        $this->lessonsTransform = $lessonsTransform;
    }
   
    public function index()
    {
        $lessons = Lesson::all();
        return response()->json([
            'status'      => 'success',
            'status_code' => 200,
            'data'        => $this->lessonsTransform->transforms($lessons->toArray()),
        ]);
    }
    public function show(Lesson $lesson)
    {
        return response()->json([
            'status'      => 'success',
            'status_code' => 200,
            'data'        => $this->lessonsTransform->transform($lesson->toArray()),
        ]);
    }

}

Api Controller

以前只處理了成功返回的狀況,實際上還包含了錯誤返回、重定向等等,所以能夠進一步完善這些功能,咱們將其封裝到 ApiController 中。

$ php artisan make:controller ApiController

實現

/app/Http/Controllers/ApiController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ApiController extends Controller
{
    private $statusCode = 200;  // 默認返回碼

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

    /**
     * 獲取返回碼
     * @return [int] [description]
     */
    public function getStatusCode()
    {
        return $this->statusCode;
    }

    /**
     * 設置返回碼,連貫操做
     * @param [object] $statusCode [description]
     */
    public function setStatusCode($statusCode)
    {
        $this->statusCode = $statusCode;
        return $this;
    }

    /**
     * 基本的響應方法
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function response($data)
    {   
        return response()->json($data);
    }

    /**
     * 錯誤響應
     * @param  string $message [description]
     * @return [type]          [description]
     */
    public function responseErrors($message = 'Not Found')
    {
        return $this->response([
            'status'      => 'failed',
            'status_code' => $this->getStatusCode(),
            'massage'     => $message
        ]);
    }

    /**
     * 請求數據的成功響應
     * @param  string $message [description]
     * @return [type]          [description]
     */
    public function responseSuccess($data, $message = 'Success')
    {
        return $this->response([
            'status'      => 'success',
            'status_code' => $this->getStatusCode(),
            'massage'     => $message,
            'data'        => $data
        ]);
    }

    /**
     * 不帶數據的狀態成功響應
     * @param  {String} $message [description]
     * @return {[type]}          [description]
     */
    public function responseOk($message ='Ok')
    {
        return $this->response([
            'status'      => 'success',
            'status_code' => $this->getStatusCode(),
            'massage'     => $message
        ]);
    }
}

控制器能夠簡化成

/app/Http/Controllers/LessonController.php
<?php

namespace App\Http\Controllers;

use App\Lesson;
use App\Transformer\LessonsTransform;
use Illuminate\Http\Request;

class LessonController extends ApiController
{
    protected $lessonsTransform;
    public function __construct(LessonsTransform $lessonsTransform)
    {
        $this->lessonsTransform = $lessonsTransform;
    }
   
    public function index()
    {
        $lessons = Lesson::all();
        return $this->responseSuccess($this->lessonsTransform->transforms($lessons->toArray()));
    }

    public function show($id)
    {
        $lesson = Lesson::find($id);
        if (!$lesson) {
            return $this->setStatusCode(400)->responseErrors('錯誤的 id 請求');
        }

        return $this->responseSuccess($this->lessonsTransform->transform($lesson->toArray()));
    }
}

附錄

相關文章
相關標籤/搜索