リレーションを使用した簡易化の確認

## はじめに
リレーションについて整理します。
しっかり使えば複雑なSQLを使用する必要はないはずです。
今回の例はすべて1対多または多対1です。

## 例
以下の例を考えます、Eloquent ORMを使用しています。
```php
$reports = Report::with([
    'location',
    'organization.tempSiteOrganizations',
    'reportDetails.equipment.equipmentType'
])->get();
```

同等のSQLは以下のようになります。
リレーションを活用すれば簡潔に書けることがわかります！
```sql
SELECT 
    reports.id AS report_id,
    locations.name AS location_name,
    organizations.name AS organization_name,
    temp_sites.name AS temp_site_name,
    report_details.start_time,
    report_details.end_time,
    equipment.name AS equipment_name,
    equipment_types.name AS equipment_type_name
FROM 
    reports
JOIN 
    locations ON reports.location_id = locations.id
JOIN 
    organizations ON reports.organization_id = organizations.id
JOIN 
    temp_site_organizations ON organizations.id = temp_site_organizations.organization_id
JOIN 
    temp_sites ON temp_site_organizations.temp_site_id = temp_sites.id
JOIN 
    report_details ON reports.id = report_details.report_id
JOIN 
    equipment ON report_details.equipment_id = equipment.id
JOIN 
    equipment_types ON equipment.equipment_type_id = equipment_types.id;
```

## ルール
Eloquent ORMを使用する際、データベーステーブルとモデルの間の関係を適切に設定するためには、いくつかのルールやベストプラクティスに従うことが重要です。これにより、複雑なSQLクエリを書く必要がなくなり、簡潔で可読性の高いコードを書くことができます。以下に、Laravel/Eloquentを使用する際のテーブル作成のルールを記載します。

### 1. テーブル名とモデル名の規則

#### テーブル名
- **複数形**を使用します。例えば、`User` モデルに対しては `users` テーブルを使用します。
- スネークケース（アンダースコアで単語を区切る）を使用します。例えば、`UserProfile` モデルに対しては `user_profiles` テーブルを使用します。

#### モデル名
- **単数形**を使用します。例えば、`users` テーブルに対しては `User` モデルを使用します。
- キャメルケース（各単語の最初の文字を大文字にする）を使用します。例えば、`user_profiles` テーブルに対しては `UserProfile` モデルを使用します。

### 2. 主キーとタイムスタンプ

- テーブルには通常、自動インクリメントの主キー `id` を使用します。
- テーブルには `created_at` と `updated_at` のタイムスタンプカラムを含めます。これらはEloquentが自動的に管理します。

### 3. 外部キーの命名規則

- 外部キーは関連するモデルの単数形の名前に `_id` を付けた形式を使用します。例えば、`posts` テーブルに `user_id` カラムを含めて `users` テーブルとのリレーションを表現します。

### 4. リレーションシップの設定

- モデル内でリレーションシップメソッドを定義します。例えば、`User` モデルが複数の `Post` を持つ場合、`User` モデルに `posts` メソッドを定義します。


### 5. その他のリレーションシップ

- **1対1**（One to One）：例えば、`User` が `Profile` を持つ場合。
- **多対多**（Many to Many）：例えば、`User` が複数の `Role` を持ち、`Role` が複数の `User` を持つ場合。
- **ポリモーフィックリレーション**：例えば、`Post` や `Comment` が `Tag` を持つ場合。

<br>
これらのルールに従うことで、Eloquent ORMを最大限に活用し、複雑なSQLクエリを書くことなく、シンプルで可読性の高いコードを書くことができます。


## テーブル構成
今回使用するテーブルを作成します。
### ER図
テーブル関係をER図で描画します。
以下の図では、各テーブルをエンティティとして、関連性を矢印で示します。

```mermaid
erDiagram
    REPORTS {
        bigint id PK
        bigint location_id FK
        bigint organization_id FK
        timestamps created_at
        timestamps updated_at
    }
    LOCATIONS {
        bigint id PK
        varchar name
        timestamps created_at
        timestamps updated_at
    }
    ORGANIZATIONS {
        bigint id PK
        varchar name
        timestamps created_at
        timestamps updated_at
    }
    TEMP_SITE_ORGANIZATIONS {
        bigint id PK
        bigint organization_id FK
        bigint temp_site_id FK
        timestamps created_at
        timestamps updated_at
    }
    TEMP_SITES {
        bigint id PK
        varchar name
        timestamps created_at
        timestamps updated_at
    }
    REPORT_DETAILS {
        bigint id PK
        bigint report_id FK
        bigint equipment_id FK
        time start_time
        time end_time
        timestamps created_at
        timestamps updated_at
    }
    EQUIPMENT {
        bigint id PK
        varchar name
        bigint equipment_type_id FK
        timestamps created_at
        timestamps updated_at
    }
    EQUIPMENT_TYPES {
        bigint id PK
        varchar name
        timestamps created_at
        timestamps updated_at
    }

    REPORTS ||--o{ LOCATIONS: "belongs to"
    REPORTS ||--o{ ORGANIZATIONS: "belongs to"
    TEMP_SITE_ORGANIZATIONS ||--o{ ORGANIZATIONS: "belongs to"
    TEMP_SITE_ORGANIZATIONS ||--o{ TEMP_SITES: "belongs to"
    REPORT_DETAILS ||--o{ REPORTS: "belongs to"
    REPORT_DETAILS ||--o{ EQUIPMENT: "belongs to"
    EQUIPMENT ||--o{ EQUIPMENT_TYPES: "belongs to"
```

このER図は、各テーブルのカラム（フィールド）とそれらのリレーションシップ（関連性）を示しています。 `PK` は主キー、`FK` は外部キーを示しています。

### テーブル構造
以下に、`Report`、`Location`、`Organization`、`TempSiteOrganizations`、`ReportDetails`、`Equipment`、および`EquipmentType`のテーブル構造の例を提示します。
#### reports
| Column         | Type         | Description                 |
|----------------|--------------|-----------------------------|
| id             | BIGINT       | Primary key                 |
| location_id    | BIGINT       | Foreign key to locations    |
| organization_id| BIGINT       | Foreign key to organizations|
| created_at     | TIMESTAMP    | Creation timestamp          |
| updated_at     | TIMESTAMP    | Update timestamp            |

#### locations
| Column     | Type     | Description         |
|------------|----------|---------------------|
| id         | BIGINT   | Primary key         |
| name       | VARCHAR  | Name of the location|
| created_at | TIMESTAMP| Creation timestamp  |
| updated_at | TIMESTAMP| Update timestamp    |

#### organizations
| Column     | Type     | Description            |
|------------|----------|------------------------|
| id         | BIGINT   | Primary key            |
| name       | VARCHAR  | Name of the organization|
| created_at | TIMESTAMP| Creation timestamp     |
| updated_at | TIMESTAMP| Update timestamp       |

#### temp_site_organizations
| Column           | Type     | Description                     |
|------------------|----------|---------------------------------|
| id               | BIGINT   | Primary key                     |
| organization_id  | BIGINT   | Foreign key to organizations    |
| temp_site_id     | BIGINT   | Foreign key to temp sites       |
| created_at       | TIMESTAMP| Creation timestamp              |
| updated_at       | TIMESTAMP| Update timestamp                |

#### report_details
| Column        | Type     | Description                   |
|---------------|----------|-------------------------------|
| id            | BIGINT   | Primary key                   |
| report_id     | BIGINT   | Foreign key to reports        |
| equipment_id  | BIGINT   | Foreign key to equipment      |
| start_time    | TIME     | Work start time               |
| end_time      | TIME     | Work end time                 |
| created_at    | TIMESTAMP| Creation timestamp            |
| updated_at    | TIMESTAMP| Update timestamp              |

#### equipment
| Column       | Type     | Description                   |
|--------------|----------|-------------------------------|
| id           | BIGINT   | Primary key                   |
| name         | VARCHAR  | Name of the equipment         |
| equipment_type_id | BIGINT | Foreign key to equipment types |
| created_at   | TIMESTAMP| Creation timestamp            |
| updated_at   | TIMESTAMP| Update timestamp              |

#### equipment_types
| Column     | Type     | Description                |
|------------|----------|----------------------------|
| id         | BIGINT   | Primary key                |
| name       | VARCHAR  | Type of the equipment      |
| created_at | TIMESTAMP| Creation timestamp         |
| updated_at | TIMESTAMP| Update timestamp           |


## マイグレーションファイル作成
テーブル作成にあたりマイグレーションを使用します。
以下に、各コマンドとそれによって生成されるマイグレーションファイルの内容をセットで記載します。

### 1. reports テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_reports_table --create=reports
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_reports_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateReportsTable extends Migration
{
    public function up()
    {
        Schema::create('reports', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('location_id');
            $table->unsignedBigInteger('organization_id');
            $table->timestamps();

            $table->foreign('location_id')->references('id')->on('locations');
            $table->foreign('organization_id')->references('id')->on('organizations');
        });
    }

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

### 2. locations テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_locations_table --create=locations
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_locations_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateLocationsTable extends Migration
{
    public function up()
    {
        Schema::create('locations', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });
    }

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

### 3. organizations テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_organizations_table --create=organizations

```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_organizations_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateOrganizationsTable extends Migration
{
    public function up()
    {
        Schema::create('organizations', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });
    }

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

### 4. temp_site_organizations テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_temp_site_organizations_table --create=temp_site_organizations
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_temp_site_organizations_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTempSiteOrganizationsTable extends Migration
{
    public function up()
    {
        Schema::create('temp_site_organizations', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('organization_id');
            $table->unsignedBigInteger('temp_site_id');
            $table->timestamps();

            $table->foreign('organization_id')->references('id')->on('organizations');
            // Assuming temp_sites table exists
            $table->foreign('temp_site_id')->references('id')->on('temp_sites');
        });
    }

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

### 5. report_details テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_report_details_table --create=report_details
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_report_details_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateReportDetailsTable extends Migration
{
    public function up()
    {
        Schema::create('report_details', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('report_id');
            $table->unsignedBigInteger('equipment_id');
            $table->time('start_time');
            $table->time('end_time');
            $table->timestamps();

            $table->foreign('report_id')->references('id')->on('reports');
            $table->foreign('equipment_id')->references('id')->on('equipment');
        });
    }

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

### 6. equipment テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_equipment_table --create=equipment
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_equipment_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateEquipmentTable extends Migration
{
    public function up()
    {
        Schema::create('equipment', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->unsignedBigInteger('equipment_type_id');
            $table->timestamps();

            $table->foreign('equipment_type_id')->references('id')->on('equipment_types');
        });
    }

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

### 7. equipment_types テーブル

#### コマンド:
```sh
./vendor/bin/sail artisan make:migration create_equipment_types_table --create=equipment_types
```

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_equipment_types_table.php`):
```php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateEquipmentTypesTable extends Migration
{
    public function up()
    {
        Schema::create('equipment_types', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });
    }

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

### 8.`temp_sites` テーブル

#### 生成されるファイル (`database/migrations/xxxx_xx_xx_xxxxxx_create_temp_sites_table.php`):

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

class CreateTempSitesTable extends Migration
{
    public function up()
    {
        Schema::create('temp_sites', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name'); 
            $table->timestamps();
        });
    }

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

## 依存関係
上記はphp artisan mygrateではエラーになります。
マイグレーションの実行順序を確認し、依存関係を正しく反映させるために、以下の順序でマイグレーションを実行します。

### マイグレーション実行順序

1. `locations` テーブル
2. `organizations` テーブル
3. `temp_sites` テーブル
4. `equipment_types` テーブル
5. `equipment` テーブル
6. `reports` テーブル
7. `temp_site_organizations` テーブル
8. `report_details` テーブル

```sh
# 順番にマイグレーションを実行
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071800_create_locations_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071802_create_organizations_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071804_create_temp_sites_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071806_create_equipment_types_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_072055_create_equipment_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071808_create_reports_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_071810_create_temp_site_organizations_table.php
./vendor/bin/sail artisan migrate --path=/database/migrations/2024_06_20_072000_create_report_details_table.php
```

## データセット
データをセットします、まずテストデータをデータベースに挿入する必要があります。以下の手順でデータをセットしていきます。

### 1. モデルとリレーションの設定

まず、各モデルのリレーションを設定します。

#### Location モデル

```sh
./vendor/bin/sail artisan make:model Location
```
```php
namespace App\Models;

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

class Location extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

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

#### Organization モデル
```sh
./vendor/bin/sail artisan make:model Organization
```
```php
namespace App\Models;

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

class Organization extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

    public function tempSiteOrganizations()
    {
        return $this->hasMany(TempSiteOrganization::class);
    }

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

#### TempSite モデル
```sh
./vendor/bin/sail artisan make:model TempSite
```
```php
namespace App\Models;

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

class TempSite extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

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

#### TempSiteOrganization モデル
```sh
./vendor/bin/sail artisan make:model TempSiteOrganization
```
```php
namespace App\Models;

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

class TempSiteOrganization extends Model
{
    use HasFactory;

    protected $fillable = ['organization_id', 'temp_site_id'];

    public function organization()
    {
        return $this->belongsTo(Organization::class);
    }

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

#### Report モデル
```sh
./vendor/bin/sail artisan make:model Report
```
```php
namespace App\Models;

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

class Report extends Model
{
    use HasFactory;

    protected $fillable = ['location_id', 'organization_id'];

    public function location()
    {
        return $this->belongsTo(Location::class);
    }

    public function organization()
    {
        return $this->belongsTo(Organization::class);
    }

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

#### ReportDetail モデル
```sh
./vendor/bin/sail artisan make:model ReportDetail
```
```php
namespace App\Models;

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

class ReportDetail extends Model
{
    use HasFactory;

    protected $fillable = ['report_id', 'equipment_id', 'start_time', 'end_time'];

    public function report()
    {
        return $this->belongsTo(Report::class);
    }

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

#### Equipment モデル
```sh
./vendor/bin/sail artisan make:model Equipment
```
```php
namespace App\Models;

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

class Equipment extends Model
{
    use HasFactory;

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

    public function equipmentType()
    {
        return $this->belongsTo(EquipmentType::class);
    }

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

#### EquipmentType モデル
```
./vendor/bin/sail artisan make:model EquipmentType
```
```php
namespace App\Models;

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

class EquipmentType extends Model
{
    use HasFactory;

    protected $fillable = ['name'];

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

### 2. シーダーでデータをセットする

データベースシーダーを作成して、テストデータを挿入します。

#### DatabaseSeeder
`database/seeders/DatabaseSeeder.php`
```php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use App\Models\Location;
use App\Models\Organization;
use App\Models\TempSite;
use App\Models\TempSiteOrganization;
use App\Models\Report;
use App\Models\ReportDetail;
use App\Models\Equipment;
use App\Models\EquipmentType;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        // 5つのロケーションを生成
        for ($i = 1; $i <= 5; $i++) {
            $location = Location::create(['name' => 'Location ' . $i]);

            // 5つの組織を生成
            for ($j = 1; $j <= 5; $j++) {
                $organization = Organization::create(['name' => 'Organization ' . $j]);

                // 1つの一時サイトを生成
                $tempSite = TempSite::create(['name' => 'Temp Site ' . $i . '-' . $j]);

                // 一時サイトと組織の関係を生成
                $tempSiteOrganization = TempSiteOrganization::create([
                    'organization_id' => $organization->id,
                    'temp_site_id' => $tempSite->id,
                ]);

                // 1つのレポートを生成
                $report = Report::create([
                    'location_id' => $location->id,
                    'organization_id' => $organization->id,
                ]);

                // 1つの機器タイプを生成
                $equipmentType = EquipmentType::create(['name' => 'Type ' . $i . '-' . $j]);

                // 1つの機器を生成
                $equipment = Equipment::create([
                    'name' => 'Equipment ' . $i . '-' . $j,
                    'equipment_type_id' => $equipmentType->id,
                ]);

                // レポート詳細を生成
                ReportDetail::create([
                    'report_id' => $report->id,
                    'equipment_id' => $equipment->id,
                    'start_time' => '08:00:00',
                    'end_time' => '17:00:00',
                ]);
            }
        }
    }
}

```

このシーダーを実行することで、データベースに必要なテストデータが挿入されます。

### 3. シーダーの実行

以下のコマンドを実行してシーダーを実行し、データを挿入します。

```sh
./vendor/bin/sail artisan db:seed
```

### 4. データの取得

これで、指定したクエリを実行してデータを取得できるはずです。

```php
$reports = Report::with([
    'location',
    'organization.tempSiteOrganizations',
    'reportDetails',
    'reportDetails.equipment.equipmentType'
])->get();
```

この手順でデータをセットし、取得することができます。他にご質問があればお知らせください。


## データ確認
シーダーが実行できたことを確認した後、データを表示させてみます。

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

データを取得して表示するためのコントローラーを作成します。

```sh
./vendor/bin/sail artisan make:controller ReportController
```

### 2. コントローラーの編集

作成したコントローラーにデータを取得してビューに渡す処理を追加します。

#### `app/Http/Controllers/ReportController.php`

```php
namespace App\Http\Controllers;

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

class ReportController extends Controller
{
    public function index()
    {
        $reports = Report::with([
            'location',
            'organization.tempSiteOrganizations',
            'reportDetails.equipment.equipmentType'
        ])->get();

        return view('reports.index', compact('reports'));
    }
}
```

### 3. ビューの作成

ビューを作成して、データを表示します。

#### ビューのファイル作成
 `resources/views/reports/index.blade.php`

```html
<!DOCTYPE html>
<html>
<head>
    <title>Reports</title>
</head>
<body>
    <h1>Reports</h1>
    @foreach ($reports as $report)
        <h2>Report ID: {{ $report->id }}</h2>
        <p>Location: {{ $report->location->name }}</p>
        <p>Organization: {{ $report->organization->name }}</p>
        <h3>Temp Site Organizations:</h3>
        <ul>
            @foreach ($report->organization->tempSiteOrganizations as $tempSiteOrganization)
                <li>{{ $tempSiteOrganization->tempSite->name }}</li>
            @endforeach
        </ul>
        <h3>Report Details:</h3>
        <ul>
            @foreach ($report->reportDetails as $detail)
                <li>
                    Start Time: {{ $detail->start_time }},
                    End Time: {{ $detail->end_time }},
                    Equipment: {{ $detail->equipment->name }},
                    Equipment Type: {{ $detail->equipment->equipmentType->name }}
                </li>
            @endforeach
        </ul>
    @endforeach
</body>
</html>
```

### 4. ルートの設定

ルートを設定してコントローラーのメソッドを呼び出すようにします。

#### `routes/web.php`

```php
use App\Http\Controllers\ReportController;

Route::get('/reports', [ReportController::class, 'index']);
```

### 5. アプリケーションの起動と確認

アプリケーションを起動してデータが表示されることを確認します。

```sh
./vendor/bin/sail up
```

ブラウザで `http://localhost/reports` にアクセスして、データが表示されることを確認します。

これで、シーダーで挿入したデータをビューで表示させることができます。


## データ取得説明
 `$reports = Report::with([...])->get();` に関する詳細な説明と、各依存関係の説明を記載します。

### コードの詳細と依存関係

```php
$reports = Report::with([
    'location',
    'organization.tempSiteOrganizations',
    'reportDetails.equipment.equipmentType'
])->get();
```
**クエリ例**
```sql
array:7 [▼ // app/Http/Controllers/ReportController.php:25
  0 => array:3 [▼
    "query" => "select * from `reports`"
    "bindings" => []
    "time" => 1.25
  ]
  1 => array:3 [▼
    "query" => "select * from `locations` where `locations`.`id` in (1, 2, 3, 4, 5, 6)"
    "bindings" => []
    "time" => 0.77
  ]
  2 => array:3 [▼
    "query" => "select * from `organizations` where `organizations`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)"
    "bindings" => []
    "time" => 0.69
  ]
  3 => array:3 [▼
    "query" => "
select * from `temp_site_organizations` where `temp_site_organizations`.`organization_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
 ◀
"
    "bindings" => []
    "time" => 0.8
  ]
  4 => array:3 [▼
    "query" => "
select * from `report_details` where `report_details`.`report_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
 ◀
"
    "bindings" => []
    "time" => 0.57
  ]
  5 => array:3 [▼
    "query" => "select * from `equipment` where `equipment`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)"
    "bindings" => []
    "time" => 0.5
  ]
  6 => array:3 [▼
    "query" => "select * from `equipment_types` where `equipment_types`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)"
    "bindings" => []
    "time" => 0.99
  ]

```

### 実行されるクエリの詳細とその意味

　1. **レポートの取得**

```sql
select * from `reports`
```
- これは`reports`テーブルからすべてのレポートを取得します。

　2. **ロケーションの取得**

```sql
select * from `locations` where `locations`.`id` in (1, 2, 3, 4, 5, 6)
```
- 取得されたレポートの`location_id`に基づいて、対応するロケーションを`locations`テーブルから取得します。

　3. **組織の取得**

```sql
select * from `organizations` where `organizations`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
```
- 取得されたレポートの`organization_id`に基づいて、対応する組織を`organizations`テーブルから取得します。

　4. **一時サイトと組織の関係の取得**

```sql
select * from `temp_site_organizations` where `temp_site_organizations`.`organization_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
```
- 取得された組織の`id`に基づいて、一時サイトと組織の関係を`temp_site_organizations`テーブルから取得します。

　5. **レポート詳細の取得**

```sql
select * from `report_details` where `report_details`.`report_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
```
- 取得されたレポートの`id`に基づいて、対応するレポート詳細を`report_details`テーブルから取得します。

　6. **機器の取得**

```sql
select * from `equipment` where `equipment`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
```
- 取得されたレポート詳細の`equipment_id`に基づいて、対応する機器を`equipment`テーブルから取得します。

　7. **機器タイプの取得**

```sql
select * from `equipment_types` where `equipment_types`.`id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
```
- 取得された機器の`equipment_type_id`に基づいて、対応する機器タイプを`equipment_types`テーブルから取得します。



### データの取得

このクエリを実行すると、`Report` のデータとその関連情報が一度に取得されます。例えば、以下のようなデータ構造が取得されます。

```php
foreach ($reports as $report) {
    echo "Report ID: " . $report->id . "\n";
    echo "Location: " . $report->location->name . "\n";
    echo "Organization: " . $report->organization->name . "\n";
    foreach ($report->reportDetails as $detail) {
        echo "Detail ID: " . $detail->id . "\n";
        echo "Equipment: " . $detail->equipment->name . "\n";
        echo "Equipment Type: " . $detail->equipment->equipmentType->name . "\n";
    }
}
```

- **`Report`** から関連する **`Location`**, **`Organization`**, **`ReportDetails`** の情報を一緒に取得しています。
- **`ReportDetail`** から **`Equipment`** とその **`EquipmentType`** の情報も取得しています。

####  `Report` モデルの関連付け

このクエリは `Report` モデルからデータを取得し、以下の関連モデルも一緒にロードしています。

- **`location`**:
  - `Report` と `Location` のリレーションです。`Report` が `Location` に属することを示します。
  - **例**: `Report` が `Location` の `id` を `location_id` として持つ。

- **`organization.tempSiteOrganizations`**:
  - `Report` と `Organization` のリレーションで、さらに `Organization` が複数の `TempSiteOrganization` と関連していることを示します。
  - **例**: `Organization` モデルに `TempSiteOrganization` モデルとのリレーションが定義されている。

- **`reportDetails.equipment.equipmentType`**:
  - `Report` の詳細情報 (`ReportDetails`) を取得し、その詳細が `Equipment` と `EquipmentType` に関連していることを示します。
  - **例**: `ReportDetails` が `Equipment` の `equipment_id` を持ち、さらにその `Equipment` が `EquipmentType` に属する。



## 比較

提供されたEloquentクエリは、SQLクエリと同等の結果を返します。Eloquent ORMを使用することで、リレーションシップを利用したデータの取得が簡潔に行えますが、内部的には以下のようなSQLクエリを実行しています。

### Eloquentクエリ

```php
$reports = Report::with([
    'location',
    'organization.tempSiteOrganizations',
    'reportDetails.equipment.equipmentType'
])->get();
```

### 同等のSQLクエリ

```sql
SELECT 
    reports.id AS report_id,
    locations.name AS location_name,
    organizations.name AS organization_name,
    temp_sites.name AS temp_site_name,
    report_details.start_time,
    report_details.end_time,
    equipment.name AS equipment_name,
    equipment_types.name AS equipment_type_name
FROM 
    reports
JOIN 
    locations ON reports.location_id = locations.id
JOIN 
    organizations ON reports.organization_id = organizations.id
JOIN 
    temp_site_organizations ON organizations.id = temp_site_organizations.organization_id
JOIN 
    temp_sites ON temp_site_organizations.temp_site_id = temp_sites.id
JOIN 
    report_details ON reports.id = report_details.report_id
JOIN 
    equipment ON report_details.equipment_id = equipment.id
JOIN 
    equipment_types ON equipment.equipment_type_id = equipment_types.id;
```


2つの結果は同じデータを返します。ただし、取得方法が異なります。


### 同じデータを取得するが、方法が異なる

- **Eloquentクエリ**：
  - 内部的に複数のSQLクエリを発行して関連データを取得します。
  - 各モデル間のリレーションシップに基づいてデータをロードします。
  - 直感的でメンテナンスが容易なコードを書くことができます。

- **SQLクエリ**：
  - 単一のクエリで複数のテーブルをJOINしてデータを取得します。
  - リレーションシップを手動で定義する必要があります。
  - SQLの知識が必要ですが、特定のシナリオではパフォーマンスが向上することがあります。

### 結果の一致

両方のアプローチは同じデータを取得しますが、Eloquentはリレーションシップを抽象化して扱いやすくし、SQLは直接的で効率的なデータ取得を行います。



## 参考記事

https://kinsta.com/jp/blog/laravel-relationships/


https://wingdoor.co.jp/blog/laravel%E3%81%AE%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E6%95%B4%E7%90%86%EF%BC%9A1%E5%AF%BE%E5%A4%9A%E3%81%AE%E3%83%AA%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%80%90hasmany/