サイトアイコン 上尾市のWEBプログラマーによるブログ

「プロフェッショナルWebプログラミングLaravel」の感想・備忘録2

基本

モデルの作成

sail artisan make:model Tweet

オプション

ファクトリーの作成

1. sail artisan make:factory TweetFactory --model=Tweet
2. definitionメソッドを修正
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Tweet>
 */
class TweetFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'user_id' => 1,
            'content' => $this->faker->realText(100) // 追加
        ];
    }
}
// ※ config/app.phpのfaker_localeをja_JPに変更しておく

TweetsSeeder

use App\Models\Tweet;を追加しrunメソッドを修正

<?php

namespace Database\Seeders;

use App\Models\Tweet;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

class TweetsSeeder extends Seeder
{
    /**
     * Run the database seeds.
     */
    public function run(): void
    {
        Tweet::factory()->count(10)->create();
    }
}

登録処理の作成

1. sail artisan make:request Tweet/CreateRequest

<?php

namespace App\Http\Requests\Tweet;

use Illuminate\Foundation\Http\FormRequest;

class CreateRequest 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\Rule|array|string>
     */
    public function rules(): array
    {
        return [
            'tweet' => 'required|max:140'
        ];
    }

    // フォームの値を取得するためのメソッドを追加
    // コントローラではなくFormRequestに実装することでコントローラの処理を簡略化することできる
    public function tweet(): string
    {
        return $this->input('tweet');
    }
}

2. sail artisan make:controller Tweet/CreateController --invokable

<?php

namespace App\Http\Controllers\Tweet;

use App\Http\Controllers\Controller;
use App\Http\Requests\Tweet\CreateRequest;
use App\Models\Tweet;
use Symfony\Component\HttpFoundation\Response;

class CreateController extends Controller
{
    /**
     * Handle the incoming request.
     */
    public function __invoke(CreateRequest $request): Response
    {
        $tweet = new Tweet();
        $tweet->user_id = $request->userId();
        $tweet->content = $request->tweet();
        $tweet->save();
        return redirect()->route('tweet.index');
    }
}

3. route/web.phpに追加

Route::post('/tweet/create', \App\Http\Controllers\Tweet\CreateController::class)->name('tweet.create');

4. touch resources/views/tweet/index.blade.php

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>つぶやきアプリ</title>
</head>
<body>
<h1>つぶやきアプリ</h1>
<div>
    <p>投稿フォーム</p>
    @if (session('feedback.success'))
        <p style="color: green">{{ session('feedback.success') }}</p>
    @endif
    <form action="{{ route('tweet.create') }}" method="post">
        @csrf
        <label for="tweet-content">つぶやき</label>
        <span>140文字まで</span>
        <textarea id="tweet-content" type="text" name="tweet" placeholder="つぶやきを入力"></textarea>
        @error('tweet')
        <p style="color: red;">{{ $message }}</p>
        @enderror
        <button type="submit">投稿</button>
    </form>
</div>
<div>
    @foreach($tweets as $tweet)
        <details>
            <summary>{{ $tweet->content }}</summary>
            <a href="{{ route('tweet.update.index', ['id' => $tweet->id]) }}">編集</a>
            <form action="{{ route('tweet.delete', ['id' => $tweet->id]) }}" method="post">
                @method('DELETE')
                @csrf
                <button type="submit">削除</button>
            </form>
        </details>
    @endforeach
</div>
</body>
</html>

モバイルバージョンを終了