この度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
http://localhost:8000/articles/3
日本語が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
まとめ
- Laravelでよく使ってたコマンドまで使えないから、たくさん詰まりましたw
- 速度面で優れるのは間違いないから、Laravelとうまく使い分けることが大事そう
- LaravelもLumenももっと理解しようってモチベ上がった
参考
たくさん参考にさせて頂きました。m(_ _)m