建立應用php
$ laravel new api-basic
建立數據庫mysql
> create database ApiBasic
配置 .env
laravel
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
/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
接下來,考慮的是對上面代碼的重構與優化。
首先是數據的轉化部分,其餘模塊也須要用到該功能,所以能夠將其抽象出來:
多條數據的轉化 - 不一樣模塊用法都相同,都是遍歷並每一條數據進行處理;
單條數據的轉換 - 不一樣模塊可根據本身的需求定製;
所以,能夠使用 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()), ]); } }
以前只處理了成功返回的狀況,實際上還包含了錯誤返回、重定向等等,所以能夠進一步完善這些功能,咱們將其封裝到 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())); } }
附錄
學習交流 QQ 羣 - 416179157