LocoPartners 開発ブログ

LocoPartners 開発者達によるブログです

CakePHPer が Laraveler に成りたくて Part.1

こんにちは。

Relux でサーバーサイドを担当している山口です。PHP が大好きです。

弊社では近頃一部の処理に Laravel を採用することになりました。今まで主に CakePHP を利用していたこともあり、未だまだ不慣れな箇所も多いですが学んだことを少しづつ当ブログを通じて発信していけたらと思います。

今回は初回ということで、簡単な API を Laravel 5.4.5 で作成し、テストをパスするまでの過程を紹介します。

Larvel でとりあえずコードを書いて試せる環境を用意する

composer の普及や built-in server が組み込まれた PHP の Version を Framework 側が要求するようになったこともあり、最近の PHP Framework はどれも環境を用意するのが非常に楽になりました。Laravel も他のフレームワーク同様に下記の手順を踏むだけで簡単に環境を用意することができます。

# Laravel のインストール
$ composer create-project --prefer-dist laravel/laravel sandbox

~~~ 省略 ~~~

Writing lock file
Generating autoload files
> Illuminate\Foundation\ComposerScripts::postUpdate
> php artisan optimize
Generating optimized class loader
The compiled services file has been removed.
> php artisan key:generate
Application key [base64:yTWzVOqqPVKjXpIxvtgSDLguGC3BDbNbzswrjFi4qaA=] set successfully.
# build-in server の起動
$ php artisan serve
Laravel development server started: <http://127.0.0.1:8000>

上記の URL (http://127.0.0.1:8000) をブラウザで開くと、オシャレなフォントで Welcome と表示され Laravel が動作していることを確認できます。 また、今回 built-in server の起動に利用した artisan コマンドは、他にも migration や各種コードの雛形の自動生成など色々と便利なことを行ってくれます。

もし、composer コマンドの途中でエラーが発生してしまった場合は Installation - Laravel - The PHP Framework For Web Artisans を満たしていないことになるので確認してみましょう。もう少しきちんとした開発環境を用意しないと気がすまない人は Laravel Homestead や Laravel Valet と呼ばれるものもあるのでそちらを試されてみるのも良いかもしれませんね。

Laravel Homestead - Laravel - The PHP Framework For Web Artisans https://laravel.com/docs/5.4/valet

API の仕様を決める

はじめに API の仕様を swagger-editor で作ります。 これは、Laravel とは関係がないので必要のない方は飛ばして頂いて問題ありません。

swagger-editor の install は npm, wget, unzip がインストールされている端末であればあっという間に終わります。 Web の開発をされている方の端末であれば大体はインストールされていると思うので、下記のコマンドを上から順に実行してみてください。

$ npm install -g http-server
$ wget https://github.com/swagger-api/swagger-editor/releases/download/v2.10.4/swagger-editor.zip
$ unzip swagger-editor.zip
$ http-server swagger-editor
Starting up http-server, serving swagger-editor
Available on:
  http://127.0.0.1:8080
  http://192.168.10.254:8080
  http://192.168.33.1:8080
Hit CTRL-C to stop the server

上記の URL (http://127.0.0.1:8080) にアクセスすると swagger-editor の画面が表示されるので、画面内で Swagger Spec V2.0 と呼ばれる決まりに従って json または yaml で仕様書を書いていきます。細かい説明は今回は省略して下記のようにドキュメントを記述しました。

swagger: '2.0'
info:
  version: "1.0.0"
  title: Uniqid API
paths:
  /uniqid:
    get:
      description: uniqid を作成
      produces:
        - application/json
      responses:
        200:
          description: |
            uniqid の作成に成功した場合
          schema:
            properties:
              uniqid:
                description: |
                  uniqid
                type: string

API のテストコードを記述する

それではテストコードからはじめていきたいと思います。 built-in server の起動に用いた artisan コマンドを用いて下記のようにユニットテストの雛形となるコードを生成しましょう。

$ php artisan make:test UniqidControllerTest --unit
Test created successfully.

tests/Unit 配下に UniqidControllerTest.php という下記のファイルが出来上がっているはずです。

<?php

namespace Tests\Unit;

use Tests\TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class UniqidControllerTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}

早速、テストを実行してみましょう。

vendor/bin/phpunit
# 上記で実行出来ない人は下記を試してみて下さい。
vendor/phpunit/phpunit/phpunit

# 実行結果
PHPUnit 5.7.9 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 415 ms, Memory: 12.00MB

OK (3 tests, 3 assertions)

うまく動きましたか?テストをパスした数が 1 ではなく 3 になっているのは予め ExampleTest.php というファイルが存在しているからです。 これで、テストの雛形とテストの実行方法がわかったと思います。

それでは、テストを仕様に沿って記述していきましょう。uniqid() の性質上返される値を特定するのは難しいため、今回は雑ですがレスポンスに uniqid の key が存在するか、そしてステータスコードは 200 かをテストするコードを記述しました。

<?php

namespace Tests\Unit;

use Tests\TestCase;

class UniqidControllerTest extends TestCase
{
    /**
     * Authentication Controller.
     *
     * @return void
     */
    public function testレスポンスにuniqidのkeyが存在する()
    {
        $response = $this->json(
            'GET',
            '/api/uniqid'
        );

        $arrayResponse = (array)json_decode($response->content());

        $response->assertStatus(200);
        $this->assertArrayHasKey('uniqi', $arrayResponse);
    }
}

再度、テストを実行してみると下記のように 1 件のテストに失敗しているはずです。

PHPUnit 5.7.9 by Sebastian Bergmann and contributors.

..F                                                                 3 / 3 (100%)

Time: 459 ms, Memory: 12.00MB

There was 1 failure:

1) Tests\Unit\UniqidControllerTest::testレスポンスにuniqidのkeyが存在する
Failed asserting that an array has the key 'uniqid'.

/Users/kenya/loco/relux_api/tests/Unit/UniqidControllerTest.php:26

これは、テストに対応する実装が存在しないからですね。 次はこのテストをパスするために API の実装を行っていきます。

API の実装

artisan コマンドを用いて下記のようにコントローラーの雛形となるコードを生成しましょう。

$ php artisan make:controller UniqidController --resource
Controller created successfully.

app/Controller 配下に UniqidController.php という下記のファイルが出来上がっているはずです。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UniqidController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        //
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        //
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}

今回は index() の部分しか必要がないのでそれ以外は削り、下記のように実装を行いました。

<?php

namespace App\Http\Controllers;

class UniqidController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $responseValue = [
            'uniqid' => uniqid(),
        ];

        return response()->json($responseValue);
    }
}

Routing を設定する

最後に作ったコントローラーを動かすために Routing を設定します。この設定ファイルは routes/api.php になるので下記の一行を足します。 コントローラー名@アクション名を第2引数に設定することで Laravel 側で UniqidController の index アクションにつなげてくれるようになっています。

Route::get('/uniqid', 'UniqidController@index');

動作を確認する

実装が完了しました。再度テストを実行してみましょう。

PHPUnit 5.7.9 by Sebastian Bergmann and contributors.

...                                                                 3 / 3 (100%)

Time: 421 ms, Memory: 12.00MB

OK (3 tests, 4 assertions)

テストを通過しました!(雑ですが…

ブラウザからも http://127.0.0.1:8000/api/uniqid にアクセスして確認してみましょう。 下記のように結果が返ってくることが確認できたら成功です。

うまく動かない場合は最初に行った server の起動を行えているか再度確認してみてください。

{
  "uniqid": "58905d5e13920"
}

お疲れ様でした。今回はここまでとなります。 簡単な処理と説明ではありますが何となく Laravel を利用した API 作りのイメージを持っていただくことが出来たのではないでしょうか。

冒頭でも述べさせていただいたように自身も未だまだ Laravel に不慣れなので、連載を通じて Laravel について知り、皆さんのお役に立てるような記事を書けていけたらなと思っておりますので今後共宜しくお願いします。

最後になりますが、弊社では PHP が大好きな方や、「山口に俺が Laravel を教えてやるよ!」という技術的に熱い人を大募集しています。 会社見学とかも気軽に行えるので良かったら下記のリンクから気軽にお申込み下さい。

www.wantedly.com