LoginSignup
0
0

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

Last updated at Posted at 2024-06-22

はじめに

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

以下の例を考えます、Eloquent ORMを使用しています。

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

同等の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_atupdated_at のタイムスタンプカラムを含めます。これらはEloquentが自動的に管理します。

3. 外部キーの命名規則

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

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

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

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

  • 1対1(One to One):例えば、UserProfile を持つ場合。
  • 多対多(Many to Many):例えば、User が複数の Role を持ち、Role が複数の User を持つ場合。
  • ポリモーフィックリレーション:例えば、PostCommentTag を持つ場合。

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

テーブル構成

今回使用するテーブルを作成します。

ER図

テーブル関係をER図で描画します。
以下の図では、各テーブルをエンティティとして、関連性を矢印で示します。

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

テーブル構造

以下に、ReportLocationOrganizationTempSiteOrganizationsReportDetailsEquipment、および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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_reports_table --create=reports

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_reports_table.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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_locations_table --create=locations

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_locations_table.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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_organizations_table --create=organizations

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_organizations_table.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 テーブル

コマンド:

./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):

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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_report_details_table --create=report_details

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_report_details_table.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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_equipment_table --create=equipment

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_equipment_table.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 テーブル

コマンド:

./vendor/bin/sail artisan make:migration create_equipment_types_table --create=equipment_types

生成されるファイル (database/migrations/xxxx_xx_xx_xxxxxx_create_equipment_types_table.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):

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 テーブル
# 順番にマイグレーションを実行
./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 モデル

./vendor/bin/sail artisan make:model Location
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 モデル

./vendor/bin/sail artisan make:model Organization
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 モデル

./vendor/bin/sail artisan make:model TempSite
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 モデル

./vendor/bin/sail artisan make:model TempSiteOrganization
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 モデル

./vendor/bin/sail artisan make:model Report
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 モデル

./vendor/bin/sail artisan make:model ReportDetail
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 モデル

./vendor/bin/sail artisan make:model Equipment
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
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

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. シーダーの実行

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

./vendor/bin/sail artisan db:seed

4. データの取得

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

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

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

データ確認

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

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

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

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

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

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

app/Http/Controllers/ReportController.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

<!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

use App\Http\Controllers\ReportController;

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

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

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

./vendor/bin/sail up

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

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

データ取得説明

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

コードの詳細と依存関係

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

クエリ例

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. レポートの取得

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

 2. ロケーションの取得

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

 3. 組織の取得

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. 一時サイトと組織の関係の取得

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. レポート詳細の取得

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. 機器の取得

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. 機器タイプの取得

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 のデータとその関連情報が一度に取得されます。例えば、以下のようなデータ構造が取得されます。

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:

    • ReportLocation のリレーションです。ReportLocation に属することを示します。
    • : ReportLocationidlocation_id として持つ。
  • organization.tempSiteOrganizations:

    • ReportOrganization のリレーションで、さらに Organization が複数の TempSiteOrganization と関連していることを示します。
    • : Organization モデルに TempSiteOrganization モデルとのリレーションが定義されている。
  • reportDetails.equipment.equipmentType:

    • Report の詳細情報 (ReportDetails) を取得し、その詳細が EquipmentEquipmentType に関連していることを示します。
    • : ReportDetailsEquipmentequipment_id を持ち、さらにその EquipmentEquipmentType に属する。

比較

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

Eloquentクエリ

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

同等の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は直接的で効率的なデータ取得を行います。

参考記事

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0