高度なバリデーションとリレーションのあるデータベース操作

Laravelを使ったウェブアプリケーション開発では、複雑なデータのバリデーションや、複数のテーブル間のリレーション（関係）を扱うことが重要です。今回は、さらに高度なバリデーションとリレーションのあるデータベース操作について記述します。

### 目次

1. 高度なバリデーション
2. リレーションのあるデータベース操作
3. 実践プロジェクトの例

### 1. 高度なバリデーション

### カスタムバリデーションルール

Laravelでは、独自のバリデーションルールを作成することができます。たとえば、ユーザー名が特定の形式に一致するかどうかを確認するカスタムバリデーションルールを作成します。

`php artisan make:rule ValidUsername`

`app/Rules/ValidUsername.php`

```php
namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class ValidUsername implements Rule
{
    public function passes($attribute, $value)
    {
        // ユーザー名はアルファベットと数字のみで構成される
        return preg_match('/^[a-zA-Z0-9]+$/', $value);
    }

    public function message()
    {
        return 'The :attribute must be a valid username (letters and numbers only).';
    }
}
```

`UserController` でこのカスタムバリデーションルールを使用します。

```php
use App\Rules\ValidUsername;

public function store(Request $request)
{
    $validated = $request->validate([
        'name' => ['required', 'max:255', new ValidUsername],
        'email' => 'required|email|unique:users',
    ]);

    $user = User::create($validated);

    return redirect('user/'.$user->id);
}
```

### 2. リレーションのあるデータベース操作

### テーブル間のリレーションの定義

データベースのリレーションには、主に以下の3種類があります。

- 一対多（One to Many）
- 多対多（Many to Many）
- 一対一（One to One）

例として、ユーザーと投稿（Post）のリレーションを考えます。

### マイグレーションの作成

`php artisan make:migration create_posts_table --create=posts`

`database/migrations/xxxx_xx_xx_create_posts_table.php`

```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        });
    }

    public function down()
    {
        Schema::dropIfExists('posts');
    }
}
```

### モデルの定義

`app/Models/User.php`

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    use HasFactory;

    protected $fillable = ['name', 'email'];

    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}
```

`app/Models/Post.php`

```php
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'content', 'user_id'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
```

### 3. 実践プロジェクトの例

### プロジェクト：ユーザーと投稿管理

1. ルートの定義

`routes/web.php`

```php
Route::get('posts', [PostController::class, 'index']);
Route::get('post/create', [PostController::class, 'create']);
Route::post('post', [PostController::class, 'store']);
```

1. コントローラーの作成

`php artisan make:controller PostController`

`app/Http/Controllers/PostController.php`

```php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::with('user')->get();
        return view('post.index', ['posts' => $posts]);
    }

    public function create()
    {
        return view('post.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => 'required|max:255',
            'content' => 'required',
            'user_id' => 'required|exists:users,id',
        ]);

        Post::create($validated);

        return redirect('posts');
    }
}
```

1. ビューの作成

`resources/views/post/index.blade.php`

```
<!DOCTYPE html>
<html>
<head>
    <title>Posts</title>
</head>
<body>
    <h1>Posts</h1>
    @foreach ($posts as $post)
        <h2>{{ $post->title }}</h2>
        <p>{{ $post->content }}</p>
        <p>Posted by: {{ $post->user->name }}</p>
    @endforeach
</body>
</html>
```

`resources/views/post/create.blade.php`

```
<!DOCTYPE html>
<html>
<head>
    <title>Create Post</title>
</head>
<body>
    <h1>Create Post</h1>
    <form action="{{ url('post') }}" method="POST">
        @csrf
        <label for="title">Title:</label>
        <input type="text" id="title" name="title">
        <br>
        <label for="content">Content:</label>
        <textarea id="content" name="content"></textarea>
        <br>
        <label for="user_id">User ID:</label>
        <input type="text" id="user_id" name="user_id">
        <br>
        <button type="submit">Create</button>
    </form>
</body>
</html>
```

### まとめ

この記事では、高度なバリデーションとリレーションのあるデータベース操作について記述しました。カスタムバリデーションルールを作成することで、より細かいデータチェックが可能になります。また、テーブル間のリレーションを利用することで、複雑なデータ構造を扱うことができます。これらの技術を習得することで、より高度なウェブアプリケーションを開発することができると思います。