Laravelのjoinについて


1. Laravelにおける内部結合
1.1. 内部結合とは?
内部結合は、二つ以上のテーブルに共通するキー(例えばIDや外部キーなど)を基準にしてテーブルを結合する方法です。この結合では、キーが一致する行のみが結果として取得されます。キーが一致しない行は結果に含まれません。
1.2. Laravelで内部結合を行う方法
Laravelのではjoinを使用すると次のように書くことで内部結合を行うことができます。
例として、Table1とTable2をkeyで結合する場合のjoin
は次のようになります。
$results = Table1::query()
->join('Table2', 'Table1.key', '=', 'Table2.key')
->get();
実際のsqlを書くとすると、次のようになります
SELECT *
FROM Table1
INNER JOIN Table2 on Table1.key = Table2.key
1.3. joinの引数
joinの引数を表にすると、次のようになっています。
引数 | 引数の内容 | 例 |
---|---|---|
1 | 結合するテーブルの名前 | ‘customers’ |
2 | 結合条件の第1項 | ‘orders.customer_id’ |
3 | 結合条件の演算子 | ‘=’ |
4 | 結合条件の第2項 | ‘customers.id’ |
2. 実際にテーブルを結合する
次の指示に従って実際にテーブルを作って試してください。laravel9を使用しています。
2.1. ステップ1: データベースの設計
以下に、2つの関連するテーブルの例を示します。
- example_users テーブル
- id (主キー)
- name (名前)
- email (メール)
- posts テーブル
- id (主キー)
- example_user_id (usersテーブルのidと関連)
- title (タイトル)
- content (内容)

2.2. 目標
SQLで内部結合を行ったときに次のようになるものをlaravelで作ってみましょう
SELECT example_users.*,posts.title,posts.content
FROM example_users
INNER JOIN posts ON posts.example_user_id = example_users.id

Laravelでは次のように表示します。

2.3. ステップ2: マイグレーションの作成
Laravelでこれらのテーブルを作成するためのマイグレーションファイルを作成します。
php artisan make:migration create_users_table
php artisan make:migration create_posts_table
マイグレーションファイルを編集し、テーブルのスキーマを定義します。それぞれ書いてmigrateしてください。
create_users_table
:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('example_users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('example_users');
}
};
create_posts_table
:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->foreignId('example_user_id')->constrained('example_users')->onDelete('cascade');
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
};

2.4. ステップ3: モデルの作成と編集
Example_user
と Post
モデルを作成し、関連を定義します。
php artisan make:model Example_user
php artisan make:model Post
Exmaple_user
: ユーザー
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Example_user extends Model
{
use HasFactory;
protected $fillable=["name","email"];
}
Post
: 投稿内容
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable=["exmple_user_id","title","content"];
}
2.5. ステップ4: Seederの作成
次に、テストデータを生成するためのSeederを作成します。
php artisan make:seeder UsersTableSeeder
php artisan make:seeder PostsTableSeeder
Seederファイルを編集し、テストデータを定義します。
2.6. ステップ5: Seederファイルの編集
Seederファイルを編集して、データを挿入します。
UsersTableSeeder
:
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Example_user;
class UsersTableSeeder extends Seeder
{
public function run()
{
Example_user::create(['name' => 'User 1', 'email' => 'user1@example.com']);
Example_user::create(['name' => 'User 2', 'email' => 'user2@example.com']);
Example_user::create(['name' => 'User 3', 'email' => 'user3@example.com']);
}
}
PostsTableSeeder
:
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\Post;
use App\Models\Example_user;
class PostsTableSeeder extends Seeder
{
public function run()
{
$users = Example_user::all();
foreach ($users as $user) {
if($user->id==3){
break;
}
for ($i = 0; $i < 3; $i++) {
if($user->id==2 && $i>0){
break;
}
Post::create([
'example_user_id' => $user->id,
'title' => "Post " . ($i + 1) . " of User " . $user->id,
'content' => "Content for post " . ($i + 1)
]);
}
}
}
}
2.7. ステップ6:データベースのマイグレーションとSeederの実行
最後に、マイグレーションを実行し、Seederでデータを挿入します。
php artisan migrate
php artisan db:seed --class=UsersTableSeeder
php artisan db:seed --class=PostsTableSeeder
これでそれぞれのテーブルに添付画像のようにデータが追加されました。

2.8. ステップ7:コントローラの使用
php artisan make:controller PostController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Example_user;
class PostController extends Controller
{
public function show() {
$posts = Example_user::join('posts', 'example_users.id', '=', 'posts.example_user_id')
->get(['example_users.*', 'posts.title','posts.content']);
return view('post', compact('posts'));
}
}
内部結合を行っているのは次の部分です。
$posts = Example_user::join('posts', 'example_users.id', '=', 'posts.example_user_id')
->get(['example_users.*', 'posts.title','posts.content']);
これで、ユーザーとその投稿を結合したテーブルを作成することができます。
2.9. ステップ7:web.phpの編集
web.phpを次のように編集します。
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PostController;
Route::get('/',[PostController::class,"show"]);
2.10. ステップ8:ビューの作成
LaravelのBladeテンプレートを使用して、データを整理して表示します。resources/views/table.blade.php
というファイルを作成し、テーブルを作成します。
<!DOCTYPE html>
<html>
<head>
<title>Users and Posts</title>
<style>
table, th, td {
border: 1px solid black;
}
th, td {
padding: 8px;
text-align: left;
}
.g{
background-color:blue;
color:white;
}
</style>
</head>
<body>
<h1>内部結合</h1>
<table>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>Email</th>
<th>Post Title</th>
<th>Post Content</th>
</tr>
@foreach ($posts as $post)
@if ($loop->iteration % 2 != 0)
<tr>
@else
<tr class="g">
@endif
<td>{{ $post->id }}</td>
<td>{{ $post->name }}</td>
<td>{{ $post->email }}</td>
<td>{{ $post->title }}</td>
<td>{{ $post->content }}</td>
</tr>
@endforeach
</table>
</body>
</html>

php artisan serve
で次のように表示されます。
