建立应用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