LoginSignup
1
0

Lumen × dockerの環境構築とLumenチュートリアル

Last updated at Posted at 2023-11-23

この度Lumenを使用することになりまして、Lumenをキャッチアップしてみます。

Lumenの記事は古いものが多かったので、モダンなバージョンを使って
キャッチアップの様子を記事化してみました🙌

対象読者

  • Laravel使ったことあるけど、Lumenってなんぞやと知りたい同じ境遇の方
  • Lumen&dockerの環境で開発してみたい方
  • Laravel使って一年の私にありがたいアドバイスをくださる神様

目的

Lumenを触ってみる目的で以下のことを実践します

  • dockerコンテナ内にlumenのインストール
  • lumenでAPIの作成
    • migrationやらcontroller作ったりする

以下のようなgetリクエストを送信して、記事の情報をjson形式でレスポンスするAPIを作成してみます

// 記事一覧
http://localhost:8080/articles

// 記事詳細
http://localhost:8080/articles/{id}

まずLumenとは

~Laravelと同じようにアプデされて、同じように開発できて、得意領域が異なる〜

  • Laravelのマイクロフレームワーク版
    • Laravelの開発チームが手掛ける
    • Laravelと近い感覚で開発が可能(コマンドや記述等)
    • Lumenは簡易アプリケーションやAPIサーバーに適する
  • 速度やメモリ消費の観点でLaravelよりLumenが優れる
    • 必要最低限のファイルなのでインストールも激早
  • 必要に応じてフルスタックフレームワークであるLaravelへのアップデートも可能(らしい)

詳しくは公式サイト: https://lumen.laravel.com/docs/10.x/installation

使用技術

  • intel Mac(OS: Sonoma 14.1)
  • lumen-framework 10 (お試しだし最新バージョン使っていきます)
  • PHP 8.1
  • MySQL 8

ファイル構成

一応以下のようなファイル構成になっています。
src下にLumenが入る想定なので、最初は空でOK

lumen-react-typescript-docker/ % tree -L 2  
.
├── Makefile (なくてOK)
├── docker
│   ├── mysql
│   └── php
├── docker-compose.yml
└── src
    ├── lumenのファイルたち

docker用意

Laravel x MySQLが動くコンテナがあれば再現可能です。
調べたらいっぱい出てくると思うので、割愛しまお好きな環境で試してくださいw

一応docker-compose.ymlのappコンテナだけ掲載しておきます。
簡易的にappコンテナ内でビルドインウェブサーバーを起動しています。(もちろんwebサーバーを用意してもOK)

version: "3.9"
services:
  app:
    build: ./docker/php
    volumes:
      - ./docker/php/php.ini:/usr/local/php/php.ini
      - ./src:/var/www/html
    ports:
      - "8000:8000"
    command: php -S 0.0.0.0:8000 -t public
  db:

docker compose up -d後、以下のことが確認できれば大丈夫です

// アプリケーションサーバー
$ docker compose exec app composer -v
$ docker compose exec app php -v

// DB (開発中はMySQLにログインしっぱなしが楽)
$ docker compose exec db bash
// mysql login
# bash-4.4# mysql -uroot -p
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel_db         |
| mysql              |
~~~

Lumenインストール

早速コンテナ内でインストールしちゃいます

// 最新版インストール
docker compose exec app composer create-project --prefer-dist laravel/lumen .

// バージョン指定
docker-compose exec app composer create-project --prefer-dist laravel/lumen=10.x .

インストール超早。。
以下のようになっていたら成功です
http://localhost:8000/

デフォルトではバージョンを返すんですね〜、Bladeなどももちろん使用可能です。
src/routes/web.php

$router->get('/', function () use ($router) {
    return $router->app->version();
});

テスト

デフォルトのテストを動かしてみましょう。artisan testコマンドないんだ。。

% docker compose exec app vendor/bin/phpunit

PHPUnit 10.4.2 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.1.25
Configuration: /var/www/html/phpunit.xml

.                                                                   1 / 1 (100%)

Time: 00:00.261, Memory: 12.00 MB

OK (1 test, 1 assertion)

動きましたね👏

artisanコマンドの追加

デフォルトでは使用可能なartisanコマンドの数が少ないです。(artisan listで確認できます)
artisanコマンド使いたい人は追加しましょう。(参考サイト

% docker-compose exec app composer require flipbox/lumen-generator
~~色々追加される~~

次にbootstrap/app.phpファイル内に以下の記述を追加します

// $app->register(App\Providers\EventServiceProvider::class);
// 以下を追記する
$app->register(Flipbox\LumenGenerator\LumenGeneratorServiceProvider::class);

再度コマンドで確認してみると使用可能なartisanコマンドが増えていることが確認できます。

% docker-compose exec app php artisan list
~~~
 make
  make:cast            Create a new custom Eloquent cast class
  make:channel         Create a new channel class
  make:command         Create a new Artisan command
  make:controller      Create a new controller class
  make:event           Create a new event class
  make:exception       Create a new custom exception class
  make:factory         Create a new model factory
  make:job             Create a new job class
  make:listener        Create a new event listener class
  make:mail            Create a new email class
  make:middleware      Create a new middleware class
  make:migration       Create a new migration file
  make:model           Create a new Eloquent model class

モデルとマイグレーションファイルを作成する

今回はArticleという名前のモデルやテーブルを作ってみます。

docker-compose exec app php artisan make:model Article -m

Laravelと同じ感じで開発できますね
マイグレーションファイルは以下のようにしてみました。

use Illuminate\Support\Facades\Date; // 追加する
~~~
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->string('title', 50);
            $table->text('body');
            $table->integer('status');
            $table->dateTime('created_at')
                ->nullable()
                ->default(Date::now());
            $table->dateTime('updated_at')
                ->nullable()
                ->default(Date::now());
        });
    }

let's migrate

docker-compose exec app php artisan migrate

DBを確認してみるとテーブルが定義できていることが確認できました🙌

mysql> show tables;
+----------------------+
| Tables_in_laravel_db |
+----------------------+
| articles             |
| migrations           |
+----------------------+
2 rows in set (0.01 sec)

mysql> SHOW FULL COLUMNS FROM articles;
+------------+-----------------+--------------------+------+-----+---------------------+----------------+---------------------------------+---------+
| Field      | Type            | Collation          | Null | Key | Default             | Extra          | Privileges                      | Comment |
+------------+-----------------+--------------------+------+-----+---------------------+----------------+---------------------------------+---------+
| id         | bigint unsigned | NULL               | NO   | PRI | NULL                | auto_increment | select,insert,update,references |         |
| title      | varchar(50)     | utf8mb4_unicode_ci | NO   |     | NULL                |                | select,insert,update,references |         |
| body       | text            | utf8mb4_unicode_ci | NO   |     | NULL                |                | select,insert,update,references |         |
| status     | int             | NULL               | NO   |     | NULL                |                | select,insert,update,references |         |
| created_at | datetime        | NULL               | YES  |     | 2023-11-16 07:19:11 |                | select,insert,update,references |         |
| updated_at | datetime        | NULL               | YES  |     | 2023-11-16 07:19:11 |                | select,insert,update,references |         |
+------------+-----------------+--------------------+------+-----+---------------------+----------------+---------------------------------+---------+

モデルの編集

生成されたArticleモデルを以下のように修正しました

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory; // 追加
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
    use HasFactory; // 追加

    protected $fillable = [
        'title', // 追加↓
        'body',
        'status',
    ];
}

HasFactoryは不要だと思うのですが、seederの生成でエラーが出たので追記しています。
Modelとfactoryをartisanコマンドで作成したら違うのかな?

Configファイルの導入

LumenにはLaravelのようにConfigファイルがデフォルトでありません。
テストデータを日本語で生成したいので、Configファイルを作成していきます。

srcフォルダ下にapp.phpを作成し、一旦以下のような内容にしておきます。
src/config/app.php

return [
    'faker_locale' => 'ja_JP',
];

次に以下の記述をbootstrap/app.phpに追記します
src/bootstrap/app.php

/** 設定ファイルの読み込み */
$app->configure('app');

一応確認

% docker compose exec app php artisan tinker 
Psy Shell v0.11.22 (PHP 8.1.25 — cli) by Justin Hileman
> config('app.faker_locale')
= "ja_JP"

反映されていますね👏

※ Laravelではtimezoneの設定はconfig/app.phpに記述しますが、Lumenでは.envを利用するみたいです

.env

APP_TIMEZONE=Asia/Tokyo // 修正

テストデータの作成

Factoryの作成

テストデータを複数生成したいので、Factoryを作成します。

docker compose exec app php artisan make:Factory ArticleFactory

以下のようにFactoryを定義しました

use App\Models\Article; // 追記
use Carbon\Carbon; // 追記
use Illuminate\Database\Eloquent\Factories\Factory;

class ArticleFactory extends Factory
{
    protected $model = Article::class; // 追記

    public function definition(): array
    {
        return [ // 追記↓
            'title' => $this->faker->word,
            'body' => $this->faker->realText(10),
            'status' => $this->faker->numberBetween(0, 1),
            'created_at' => Carbon::now(),
            'updated_at' => Carbon::now(),
        ];
    }
}

Seederの作成

Factoryの定義を元にテストデータを作成する記述をSeederにて行います。
以下のコマンドでSeederを生成します。

docker compose exec app php artisan make:seeder ArticleTableSeeder

Seeder自体は以下のようにしました

use App\Models\Article; // 追記
use Illuminate\Database\Seeder;

class ArticleTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Article::factory(10)->create(); // 追記
    }
}

DatabaseSeederに定義

Seederを使うためにdatabase/seeds/DatabaseSeeder.phpに、作成したシーダークラスを定義します。

/**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        // $this->call('UsersTableSeeder');
        $this->call(ArticleTableSeeder::class); // 追加
    }

ダミーデータの生成

以下のコマンドで生成します。

 % docker compose exec app php artisan db:seed

   INFO  Seeding database.  

  Database\Seeders\ArticleTableSeeder .............................................................. RUNNING  
  Database\Seeders\ArticleTableSeeder ....................................................... 199.37 ms DONE 

DBにデータが入っていることも確認しておきます。

mysql> select * from articles;
+----+--------------+--------------------------------+--------+---------------------+---------------------+
| id | title        | body                           | status | created_at          | updated_at          |
+----+--------------+--------------------------------+--------+---------------------+---------------------+
|  1 | perspiciatis | 光りんこうに思いま。           |      0 | 2023-11-22 00:19:52 | 2023-11-22 00:19:52 |
|  2 | inventore    | ぼくもうしてっぽが。           |      1 | 2023-11-22 00:19:52 | 2023-11-22 00:19:52 |
|  3 | sapiente     | あかり注文ちゅうは。           |      1 | 2023-11-22 00:19:52 | 2023-11-22 00:19:52 |

日本語に対応しているFakerは日本語に、now()として登録した時間が日本時間なのも確認できました◎

コントローラーの作成

今回使用しないものもありますが、リソースコントローラーを以下のコマンドで作成しましょい

% docker compose exec app php artisan make:controller ArticleController --resource
Controller created successfully.

ルーティングの追加

src/routes/web.phpに以下の記述を追加します。

// index
$router->get('articles', 'ArticleController@index');
// show
$router->get('articles/{id}', 'ArticleController@show');

LaravelだとRoute::resource('articles', 'ArticleController');と書けますが、Routeファサードがデフォルトで使えないっぽいので、一つずつ宣言します。

ルーティングの確認

artisan route:listは使えないようですね。
以下のようにtinkerを用いて、app('router')->getRoutes();のコマンドを叩いてルーティングの確認を行います。

% docker-compose exec app php artisan tinker
Psy Shell v0.11.22 (PHP 8.1.25 — cli) by Justin Hileman
> app('router')->getRoutes();
= [
    "GET/" => [
      "method" => "GET",
      "uri" => "/",
      "action" => [
        Closure() {#20 …2},
      ],
    ],
    "GET/articles" => [
      "method" => "GET",
      "uri" => "/articles",
      "action" => [
        "uses" => "App\Http\Controllers\ArticleController@index",
      ],
    ],
    "GET/articles/{id}" => [
      "method" => "GET",
      "uri" => "/articles/{id}",
      "action" => [
        "uses" => "App\Http\Controllers\ArticleController@show",
      ],
    ],
  ]

> 

Eloquentを使用可能にする

bootstrap/app.phpにて,$app->withEloquent();のコメントアウトを外します。

コントローラを編集する

以下のように記述しました。(options: JSON_PRETTY_PRINTとするとjsonが整形されて画面で見やすいです)

use App\Models\Article; // 追加

class ArticleController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $articles = Article::all();
        return response()->json(data: $articles, options: JSON_PRETTY_PRINT);;
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $article = Article::find($id);
        return response()->json($article);
    }
}

画面でレスポンスを確認する

http://localhost:8000/articles
スクリーンショット 2023-11-23 17.01.16.png

http://localhost:8000/articles/3
スクリーンショット 2023-11-23 17.23.00.png

日本語がUnicodeエスケープされていますが、クライアントで受け取った際には解除されるっぽいので問題はない。。はず。。確認するか。。

viewの作成

indexの方だけ確認してみます。
src/resources/views/articles/index.blade.phpを作成します

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Article List</title>
</head>
<body>

<div>
    @foreach($articles as $article)
        <div>
            <h2>{{ $article['title'] }}</h2>
            <p>{!! $article['body'] !!}</p>
        </div>
    @endforeach
</div>

</body>
</html>

続いてsrc/app/Http/Controllers/ArticleController.phpのindex()内を以下のようにします

$articles = Article::all();
// return response()->json(data: $articles, options: JSON_PRETTY_PRINT);
return view('articles.index', compact('articles')); // 追加

クライアント側で受け取った際に、無事に解除されていますね!
http://localhost:8000/articles
スクリーンショット 2023-11-23 17.44.09.png

まとめ

  • Laravelでよく使ってたコマンドまで使えないから、たくさん詰まりましたw
  • 速度面で優れるのは間違いないから、Laravelとうまく使い分けることが大事そう
  • LaravelもLumenももっと理解しようってモチベ上がった

参考

たくさん参考にさせて頂きました。m(_ _)m

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0