はじめに
速習Laravelを読み、Laravelの勉強をしたので、備忘録としてコマンドをまとめておきます。
テーブルを追加
テーブルを追加して、テストデータを投入するまでの一連のコマンドをまとめます。
マイグレーションファイルを作成
php artisan make:migration create_items_table
マイグレーションファイルを編集
database/migrations
にファイルが作成されるのでファイルを編集する
// 一部抜粋
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('price');
$table->timestamps();
});
}
マイグレーションを実行
php artisan migrate
モデルを作成
php artisan make:model Item
モデルはapp/Models
に作成されます。
中身は何も書かれていませんが、EloquentというORMがモデル名からデータベースのテーブルを解決して、DBのテーブルを参照します。(Itemの場合は、itemsというテーブルを参照します)
テストデータ作成のためのファクトリーを作成
php artisan make:factory ItemFactory
ファクトリーを編集
database/factories
に作成されるので、データを生成する定義を行います
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Item>
*/
class ItemFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'name' => $this->faker->word(),
'price' => $this->faker->numberBetween(1000, 5000),
];
}
}
ダミーデータを作成するため、fakerを使用しています。
他にも調べてみると、便利そうなものがたくさんありました。
https://www.wantedly.com/companies/logical-studio/post_articles/916638
モデルを編集
ファクトリーを使用するためモデルを編集します
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
class Item extends Model
{
//
+ use HasFactory;
}
テストデータを追加するためのSeederを作成
php artisan make:seeder ItemssTableSeeder
Seederを編集
database/seeders
に作成されるので編集します。
<?php
namespace Database\Seeders;
use App\Models\Item;
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Seeder;
class ItemsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
DB::table('items')->truncate();
Item::factory()->count(10)->create();
}
}
テストデータを投入
php artisan db:seed --class=ItemsTableSeeder
結果
APIを作成
APIの機能をインストール
php artisan install:api
リクエストを作成
php artisan make:request CreateItemRequest
リクエストのクラスは作成しなくても問題ないですが、バリデーションを使用する場合は必要となります。専用のリクエストクラスを作成し、オーバーライドしないと、バリデーションエラー時リダイレクトされるようです。
リクエストの中身を実装
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Contracts\Validation\Validator;
class CreateItemRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*/
public function authorize(): bool
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
*/
public function rules(): array
{
return [
'name' => 'required|string|max:100',
'price' => 'required|numeric|min:0',
];
}
protected function failedValidation(Validator $validator)
{
$response['errors'] = $validator->errors()->toArray();
throw new HttpResponseException(response()->json($response, 422));
}
}
コントローラー作成
php artisan make:controller ItemController
コントローラの中身を実装
app/HTTP/Controllers
に作成されます
<?php
namespace App\Http\Controllers;
use App\Http\Requests\CreateItemRequest;
use App\Models\Item;
class ItemController extends Controller
{
public function create(CreateItemRequest $req)
{
$validated = $req->validated();
$item = new Item();
$item->name = $validated['name'];
$item->price = $validated['price'];
$item->save();
return response()->json([
'message' => 'Item created successfully!',
'data' => $item,
], 201);
}
}
APIのルートを定義
routes/api.php
に以下を追加します。
Route::post('/items', '\App\Http\Controllers\ItemController@create');
api.phpに定義すると、/api/booksのようなパスになる。
また、web.phpに定義した場合、POSTするときにCSRFがないとエラーになるが、api.phpはなくても問題ない。
php artisan route:list
で定義しているルート一覧を確認できる
APIを実行
curl -X POST localhost:8000/api/items -H "Content-Type: application/json" -d '{"name": "test", "price": 3000}'
ミドルウェアを追加
ミドルウェアを作成
php artisan make:middleware LogMiddleware
ミドルウェア実装
作成すると、app/Http/Middleware
にファイルが作成されるので、実装します
public function handle(Request $request, Closure $next): Response
{
$method = $request->method();
$path = $request->path();
file_put_contents(storage_path('logs/access.log'), date('Y-m-d H:i:s') . " $method $path\n", FILE_APPEND);
return $next($request);
}
登録
ルートに登録します。
Route::get('/books/{id}', '\App\Http\Controllers\BookController@getBook')->whereNumber('id')->middleware(LogMiddleware::class);
// 複数の場合
Route::get('/books/{id}', '\App\Http\Controllers\BookController@getBook')->whereNumber('id')->middleware(LogMiddleware::class, AnyMiddleware::class);
アクション後に実行する場合
アクション後に実行する場合は、実装したミドルウェアを下記にようにします。
public function handle(Request $request, Closure $next): Response
{
// $method = $request->method();
// $path = $request->path();
// file_put_contents(storage_path('logs/access.log'), date('Y-m-d H:i:s') . " $method $path\n", FILE_APPEND);
$response = $next($request);
// レスポンス内容を取得
$content = $response->getContent();
file_put_contents(storage_path('logs/access.log'), date('Y-m-d H:i:s') . " $content\n", FILE_APPEND);
return $response;
}
他の登録方法
グローバル
app/bootstrap/app.php
で定義する
<?php
use App\Http\Middleware\LogMiddleware;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__ . '/../routes/web.php',
api: __DIR__ . '/../routes/api.php',
commands: __DIR__ . '/../routes/console.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$middleware->append(LogMiddleware::class);
})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();
グループ
ルート定義でgroupを登録できます。
Route::middleware([\App\Http\Middleware\LogMiddleware::class])->group(function () {
Route::post('/books', '\App\Http\Controllers\BookController@create');
Route::get('/books/{id}', '\App\Http\Controllers\BookController@getBook')->whereNumber('id')->middleware(LogMiddleware::class);
});
Route::get('/books', '\App\Http\Controllers\BookController@getBooks');
Route::post('/items', '\App\Http\Controllers\ItemController@create');