Tech memo

日々学んだ技術のびぼうろく

Lumen で RESTful API を作ってみた

つくるもの

  • 記事(posts)の取得、新規作成、更新、削除を行える API をつくる。
  • Laravel の Resource Controllers / Resource Route をまねる。

Lumen では、Laravel の

Route::resource('photo', 'PhotoController');

に対応していないため、Resource Controllers / Resource Route の部分は自作する必要がある。

作成した API のルーティングはこんな感じ。

HTTPメソッド パス アクション
GET /api/v1/post index()
POST /api/v1/post store()
GET /api/v1/post/{id} show()
PUT /api/v1/post/{id} update()
DELETE /api/v1/post/{id} destroy()

ちなみに全ソースコートはここ。

スポンサーリンク

前提

  • Lumen 5.3

Lumen コマンドで新規アプリケーション作成

Lumenコマンド で 新規アプリケーションを作成する。
Lumenコマンドのインストール方法はこちら。

プロジェクトディレクトリに移動。

$ cd /var/www/html

アプリケーション名を mylumen とし、Lumenコマンドで新規プロジェクト作成。

$ lumen new mylumen

アプリケーションの作成が終わったらアプリケーションディレクトリに移動しておく。

$ cd mylumen

次に .env.example をコピーして .env を作成する。
APP_KEY は、

$ php -r "require 'vendor/autoload.php'; echo str_random(32).PHP_EOL;"

で吐き出された値を設定する。

APP_ENV=local
APP_DEBUG=true
APP_KEY=[your app key]
APP_TIMEZONE=Asia/Tokyo

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=mylumen
DB_USERNAME=[your db user name]
DB_PASSWORD=[your db pass]

CACHE_DRIVER=memcached
QUEUE_DRIVER=sync

最後に、Facade と Eloquent を使用可能にするため、
bootstrap/app.php

// $app->withFacades();

// $app->withEloquent();

部分のコメントアウトを外しておく。

DB の作成

sql で mylumen データベースを作成する。

CREATE DATABASE mylumen;

次に、Lumen の Migrate機能を使用して postsテーブルを作成する。

$ php artisan make:migration create_posts_table --create posts

database/migrations ディレクトリ以下に [現在日時]_create_posts_table.php という名前のマイグレートファイルが作成されるので、
up() 内を下記のように修正する。

public function up()
{
    Schema::create('posts', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('title');
        $table->text('text');
        $table->timestamps();
    });
}

テーブル定義ができたら、マイグレートを実行してテーブルを作成する。

$ php artisan migrate

テーブルができた!

mysql> desc posts;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name       | varchar(255)     | NO   |     | NULL    |                |
| title      | varchar(255)     | NO   |     | NULL    |                |
| text       | text             | NO   |     | NULL    |                |
| created_at | timestamp        | YES  |     | NULL    |                |
| updated_at | timestamp        | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+

最後に、postsテーブルに適当なダミーデータを流し込んでおく。

INSERT INTO posts (`name`, `title`, `text`, `created_at`, `updated_at`) 
values('Alex', 'dummy title.', 'dummy text.dummy text.dummy text.dummy text.', NOW(), NOW()),
('Jane', 'example title.', 'example text.example text.example text.example text.', NOW(), NOW()),
('Tonny', 'test title.', 'test text.test text.test text.test text.', NOW(), NOW());
mysql> select * from posts\G
*************************** 1. row ***************************
        id: 1
      name: Alex
     title: dummy title.
      text: dummy text.dummy text.dummy text.dummy text.
created_at: 2017-01-17 10:57:03
updated_at: 2017-01-17 10:57:03
*************************** 2. row ***************************
        id: 2
      name: Jane
     title: example title.
      text: example text.example text.example text.example text.
created_at: 2017-01-17 10:57:03
updated_at: 2017-01-17 10:57:03
*************************** 3. row ***************************
        id: 3
      name: Tonny
     title: test title.
      text: test text.test text.test text.test text.
created_at: 2017-01-17 10:57:03
updated_at: 2017-01-17 10:57:03

モデルの作成

posts テーブルを扱うためのモデルを作成する。
ディレクトリは app/Post.php とし、新規ファイルを作成して下記のコードを記述する。

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model 
{
    protected $fillable = ['name', 'title', 'text'];
}

Route の作成

Route は routes/web.php に定義されている。
今回、Laravel の Resource Route のようなことをしたいため、
routes 内に function を定義し、それを使ってルーティングを行っていく。

<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
$app->get('/', function () use ($app) {
    return $app->version();
});


$app->group(['prefix' => 'api/'.env('API_VERSION', 'v0')], function($app)
{
    resource('post', 'PostController');
});


function resource($uri, $controller)
{
    global $app;
    $app->get($uri, $controller.'@index');
    $app->post($uri, $controller.'@store');
    $app->get($uri.'/{id}', $controller.'@show');
    $app->put($uri.'/{id}', $controller.'@update');
    $app->delete($uri.'/{id}', $controller.'@destroy');
}

Resource Route に限らず、このように共通化された route を使うことで、 各 Controller の メソッド も共通化でき便利。

また、$app->group(['prefix' => 'api/'.env('API_VERSION', 'v0')], function($app) の部分で、
api のバージョンを .envファイルに記載するよう変更しているため、.env

API_VERSION=v1

を付け加える。

これで以下のようなルーティングになる。

HTTPメソッド パス アクション
GET /api/v1/post index()
POST /api/v1/post store()
GET /api/v1/post/{id} show()
PUT /api/v1/post/{id} update()
DELETE /api/v1/post/{id} destroy()

Controller の作成

Resource Route っぽい Resource Controller を作成する。 ファイルは app/Http/Controllers/PostController.php
ちなみに、Postmanなどで動作確認する場合は、Content-Type を
POST : form-data
PUT : x-www-form-urlencoded
に設定する。

<?php namespace App\Http\Controllers;

use Laravel\Lumen\Routing\Controller as BaseController;
use Illuminate\Http\Request;
use App\Post;

class PostController extends BaseController 
{
    /**
     * Display a listing of the resource.
     *
     * @return Response
     */
    public function index()
    {
        $response = Post::all();
        return response()->json($response);
    }

     /**
     * Store a newly created resource in storage.
     *
     * @param  Request  $request
     * @return Response
     */
    public function store(Request $request)
    {
        $response = Post::create($request->all());
        return response()->json($response);
    }
 
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return Response
     */
    public function show($id)
    {
        $response = Post::find($id);
        return response()->json($response);
    }

     /**
     * Update the specified resource in storage.
     *
     * @param  Request  $request
     * @param  int  $id
     * @return Response
     */
    public function update(Request $request, $id)
    {
        $updates = $request->all();
        unset($updates['q']);

        $response = false;
        $response = Post::where('id', '=', $id)->update($updates);
        if ($response === 1) $response = true;
        return response()->json($response);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return Response
     */
    public function destroy($id)
    {
        $response = false;
        $response = Post::destroy($id);
        if ($response === 1) $response = true;
        return response()->json($response);
    }
}

エラー処理などは何もしてないけど、これで一通り完成!

参考

関連記事

www.yjhm214.com

www.yjhm214.com

スポンサーリンク