
2千分後の私へ。
もくじ
ポイント
App/Http/Models/Job.php
<?php
namespace App\Http\Models;
use App\User;
use Illuminate\Database\Eloquent\Model;
class Job extends Model
{
public function users()
{
return $this->belongsToMany('App\Http\Models\Users',
'user_job',
'job_id',
'user_id');
}
- 第1引数:リレーション先のモデル名
- 第2引数:リレーション先のテーブル名
- 第3引数:自モデルの主キー
- 第4引数:相手モデルの主キー
App/Http/Models/User.php
<?php
namespace App\Http\Models;
use Illuminate\Database\Eloquent\Model;
class Users extends Model
{
public function departs()
{
return $this->belongsToMany('App\Http\Models\job',
'user_job',
'user_id',
'job_id');
}
こちらも引数を同じにします。
あとはuser_jobの中間テーブルを作成すれば良い。
指定したjob_idを持つユーザの名前とidを取得する例
$jobUsers = $job->find($job_id)->users()->pluck('name', 'id')
以下ゆっくり解説🐱✨
テーブルはこんな感じ
users
| user_id | role | name | create_at | updated_at | |
| 1 | 1 | yuu | yuu@example.net | 2019-12-29 03:18:05 | 2019-12-29 03:18:05 |
devices
| udid | device_name | create_at | updated_at |
| 1 | windows_phone | 2019-12-29 03:25:09 | 2019-12-29 03:25:09 |
| 2 | ios | 2019-12-29 03:18:05 | 2019-12-29 03:18:05 |
| 3 | android | 2019-12-29 03:25:09 | 2019-12-29 03:25:09 |
user_device_chains
| user_id | udid |
| 1 | 2 |
| 1 | 3 |
中間テーブルのマイグレーションファイルの注意
user_device_chainsテーブル定義ファイル
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
class CreateUserDeviceChainsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
Schema::create('user_device_chains', function (Blueprint $table) {
$table->unsignedBigInteger('user_id')->nullable(true)->comment('users.user_id - 会員情報id');
$table->string('udid')->nullable(true)->comment('devices.udid - デバイスid');
$table->foreign('user_id')
->references('user_id')
->on('users')
->onDelete('cascade');
$table->foreign('udid')
->references('udid')
->on('devices')
->onDelete('cascade');
$table->primary(['user_id', 'udid']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_device_chains');
}
}
ポイント① BigIncrementで生成されたid列はunsignedBigIntegerで指定する
$table->unsignedBigInteger('user_id')->nullable(true)->comment('users.user_id - 会員情報id');
$table->string('udid')->nullable(true)->comment('devices.udid - デバイスid');
ポイント② 外部キー制約
$table->foreign('user_id')
->references('user_id')
->on('users')
->onDelete('cascade');
$table->foreign('udid')
->references('udid')
->on('devices')
->onDelete('cascade');
ポイント③ 複合主キーの設定
$table->primary(['user_id', 'udid']);
これを設定しないとパフォーマンスが落ちる
users
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('user_id')->comment('会員情報テーブル主キー');
$table->integer('user_role_id')->comment('会員種別');
$table->string('user_name')->nullable(true)->comment('会員名');
$table->string('email')->nullable(true)->comment('email');
$table->timestamp('created_at')->nullable()->comment('作成日時');
$table->timestamp('updated_at')->nullable()->comment('更新日時');
$table->index('email');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
ポイント① whereで検索されるものはindexをつける
$table->index('email');
devices
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
class CreateUserDevicesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('devices', function (Blueprint $table) {
$table->string('udid')->comment('devices.udid devicesテーブル主キー');
$table->string('device_name')->comment('ツール名');
$table->timestamp('created_at')->nullable()->comment('作成日時');
$table->timestamp('updated_at')->nullable()->comment('更新日時');
$table->index('udid');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('devices');
}
}
リレーション定義
Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
protected $carbon;
protected $now;
protected $primaryKey = 'user_id';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $guarded = [
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function devices()
{
return $this->belongsToMany('App\Models\Device',
'user_device_chains',
'user_id',
'udid');
}
public function userRoles()
{
return $this->belongsTo(UserRole::class, 'user_role_id', 'user_role_id');
}
・・・
Models/Devices.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Device extends Model
{
protected $primaryKey = 'udid';
protected $guarded = [
];
public function users()
{
return $this->belongsToMany('App\Models\User',
'user_device_chains',
'udid',
'udid');
}
}
Tinkerで確認
Userの確認
bash-5.0# php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.11 — cli) by Justin Hileman
>>> use App\Models
>>> User::find(1)
[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> App\Models\User {#3089
user_id: 1,
user_role_id: 1,
user_name: yuu,
email: yuu@example.net
}
Devicesから
>>> User::find(1)->devices
=> Illuminate\Database\Eloquent\Collection {#3101
all: [
App\Models\Device {#3105
udid: "2",
device_name: "ios",
created_at: "2019-12-29 03:18:05",
updated_at: "2019-12-29 03:18:05",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3098
user_id: 1,
udid: "1",
},
},
App\Models\Device {#3102
udid: "3",
device_name: "android",
created_at: "2019-12-29 03:25:09",
updated_at: "2019-12-29 03:25:09",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3089
user_id: 1,
udid: "3",
},
},
],
}
リレーション先の値を利用した検索
iosを持っているかつ、user_role_idが1のuserを検索
$device_name = 'ios'
$user_role_id = 1;
$user = User::whereHas('devices', function($query) {
$query->where('devices.name', $device_name);
})->where('users.user_role_id', $user_role_id)
->get();
- whwreHasの中のfunction() {$query->where(‘devices.name’, $device_name);}で結合条件を指定してjoinさせて、
- 結合したデータに対して最後にwhere(‘users.user_role_id’, $user_role_id)で行を絞り混み
中間テーブルにデータを挿入する時はattach()を利用する
DB::beginTransaction();
try {
$user = new User();
$user->user_name = $request->user_name;
$user->email = $request->email;
$user->password = $request->password;
$user->save();
$user_id = $user->user_id;
$udid = $request->udid;
$device_name = $request->device_name;
$userDevice = new Device();
$userDevice->timestamps = false;
Device::create([
'udid' => $udid,
'device_name' => $device_name
]);
$user->devices()->attach(
['user_id' => $user_id],
['udid' => $udid],
['created_at' => $this->now],
['updated_at' => $this->now]
);
DB::commit();
return response()->json(config('mail.message.add_user_success'));
} catch (\Exception $e) {
DB::rollback();
Log::error('WEB /users/me/verify - Class ' . get_class() . ' - PDOException Error. Rollback was executed.' . $e->getMessage());
return response()->json(config('error.databaseTransactionRollback'));
}
外部キー制約をかけているので順番があります。
- usersテーブルにレコード挿入
- devicesテーブルにレコード挿入
- 中間テーブルにレコード挿入
Insertしたレコードのidを知りたい時
save()を行ってからプロパティで取得する
$instance->save(); $instance->id;
usersテーブルにレコードを挿入した時の例
$user = new User(); $user->user_name = $request->user_name; $user->email = $request->email; $user->password = $request->password; $user->save(); $user_id = $user->user_id; echo $user_id; // 2
usersテーブルのidのカラムはuser_idなので合わせて対応しています。
中間テーブルのカラムを取得する

