こんにちは、最近またLaravelをゴリゴリ書いています。
以前Laravelを使ってからもう1.5年ほど経って、色々とお作法が変わっていたり忘れていたりしたので結構戸惑いました。
とくに、データベースのリレーションには苦労しましたです、はい…
ということで、タイトルの通り「複数のカラムの値を使って、別のテーブルのデータを絞り込んだ上で取り込みたい!」という願いを叶える方法を書き残しておきます。
上級サブクエリというなんかすごそうな名前の機能を使う
Laravelのドキュメントでいうと、下記のページにやり方が記載されています。
この中の上級サブクエリを使って求める結果を得るのです。
まず、下記のようなテーブルを用意します。
companies
id | name |
---|---|
1 | 有限会社倉敷 |
2 | 株式会社足軽 |
3 | 株式会社 |
branch_offices
id | name | company_id |
---|---|---|
1 | 東京本社 | 1 |
2 | 愛知本社 | 2 |
3 | 神奈川本社 | 3 |
4 | 長野支社 | 1 |
5 | 沖縄支社 | 1 |
6 | 東京支社 | 2 |
7 | 北海道支社 | 3 |
emproyees
id | name | company_id | branch_office_id |
---|---|---|---|
1 | 徳川 | 1 | 1 |
2 | 織田 | 1 | 4 |
3 | 上杉 | 1 | 5 |
4 | 源 | 2 | 2 |
5 | 坂本 | 2 | 6 |
6 | 西郷 | 3 | 7 |
これらをもとに、社名と勤務先を含んだ従業員 (emproyee) 一覧を作りたいとします。
そうなるとですよ、会社名はいいとして、勤め先の本社や支社は company_id, branch_office_id を使って絞り込む必要があるわけです。
最終的には下記のようなデータが欲しいわけですよ。
ID | 名前 | 会社名 | 支店名 |
---|---|---|---|
1 | 徳川 | 有限会社幕末 | 東京本社 |
2 | 西郷 | 有限会社幕末 | 長野支社 |
3 | 中岡 | 有限会社幕末 | 沖縄支社 |
4 | 上杉 | 株式会社戦国 | 愛知本社 |
5 | 織田 | 株式会社戦国 | 東京支社 |
6 | スサノオ | 株式会社ヤマト | 北海道支社 |
Modeでサブクエリを書く
これを実現するために書くコードは下記の通り。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Customer extends Model
{
use HasFactory;
public function company()
{
return $this->belongsTo(Company::class);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Employee;
use App\Models\BranchOffice;
class HomeController extends Controller
{
public function home(Request $request)
{
$query = Employee::addSelect(['branch_office' => BranchOffice::select('name')
->whereColumn('company_id', 'branch_offices.company_id')
->whereColumn('branch_office_id', 'branch_offices.id')]);
$employees = $query->get();
foreach ($employees as $employee) {
static $employeesArray;
$employeesArray[] = [
'id' => $employee->id,
'name' => $employee->name,
'company' => $employee->company->name,
'branch_office' => $employee->branch_office,
];
};
return view('welcome', ['employees' => $employeesArray]);
}
}
ということで、addSelect
のサブクエリでwhereColumn
を2つ繋げばいいというだけでした。
わかってみれば非常に簡単に組み立てられますね。
この手の道具は普段から触っておかないとだめだな…