#Eloquentについて
データベースとモデルを紐つける機能
#1対1
##例題
今回はUsersとProfilesテーブルの連携について考えます。
ユーザーを管理するテーブルにはidとnameカラムがあります。
プロフィールを管理するテーブルにはidとuser_idとurlがあります。
1対1のリレーションでは1人のユーザーは1つのプロフィールを持っていることが前提となります。
#Userモデルの作成
$ php artisan make:model User -m
Model created successfully.
Created Migration: 2020_01_14_084605_create_users_table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
+ $table->string('name');
$table->timestamps();
});
}
#Profileモデルの作成
$ php artisan make:model Profile -m
Model created successfully.
Created Migration: 2020_01_14_090207_create_profiles_table
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
+ $table->integer('user_id');
+ $table->string('url');
$table->timestamps();
});
}
##ポイント
UserモデルにhasOneを定義
テーブル間の関係はuserテーブルのidをprofileテーブルのuser_idで紐つける。
##Userモデルに定義する
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function profile() {
return $this->hasOne(Profile::class);
}
}
#Profileモデルに定義する
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
}
##データベースにデータを挿入する。
###DatabaseSeeder.phpを編集
public function run()
{
$this->call(UsersTableSeeder::class);
$this->call(ProfilesTableSeeder::class);
}
###UsersTableSeeder.php
###ProfilesTableSeeder.php
#tinkerで確認
$ php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman
>>> $user = User::find(1);
[!] Aliasing 'User' to 'App\User' for this Tinker session.
=> App\User {#2980
id: 1,
name: "Enomoto Riko",
created_at: "2020-01-14 09:13:35",
updated_at: "2020-01-14 09:13:35",
}
>>> $user->profile;
=> App\Profile {#2983
id: 4,
user_id: 1,
url: "https://1",
created_at: "2020-01-14 09:22:02",
updated_at: "2020-01-14 09:22:02",
}
>>>
#1対多
例)ユーザーを管理しているuserテーブルとユーザーが注文したNoを管理しているordersテーブルで考えてみる。ユーザーはたくさんの注文をしており、注文は整数のNoで管理されている。
##Orderモデルの作成
php artisan make:model Order -m
Model created successfully.
Created Migration: 2020_01_23_124628_create_orders_table
##odersテーブルを作成
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->integer('order_no');
$table->timestamps();
});
}
$ php artisan migrate
Migrating: 2020_01_23_124628_create_orders_table
Migrated: 2020_01_23_124628_create_orders_table (0.03 seconds)
#seederファイルの作成
php artisan make:seeder OrdersTableSeeder
Seeder created successfully.
##OrdersTableSeederの編集
public function run()
{
DB::table('orders')->insert([
['user_id' => 3,'order_no' => '00001','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 3,'order_no' => '00002','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 4,'order_no' => '00003','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 2,'order_no' => '00004','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 1,'order_no' => '00005','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 3,'order_no' => '00006','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 5,'order_no' => '00007','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 1,'order_no' => '00008','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 4,'order_no' => '00009','created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_id' => 5,'order_no' => '00010','created_at' => new Datetime(),'updated_at' => new Datetime()],
]);
}
##DatabaseSeeder.phpの編集
##seederの実行
#tinkerで確認
$user = User::find(1);
=> App\User {#2973
id: 1,
name: "Enomoto",
created_at: "2020-01-23 13:15:07",
updated_at: "2020-01-23 13:15:07",
}
>>> $user->order;
=> Illuminate\Database\Eloquent\Collection {#3001
all: [
App\Order {#2998
id: 5,
user_id: 1,
order_no: "00005",
created_at: "2020-01-23 13:15:07",
updated_at: "2020-01-23 13:15:07",
},
App\Order {#2997
id: 8,
user_id: 1,
order_no: "00008",
created_at: "2020-01-23 13:15:07",
updated_at: "2020-01-23 13:15:07",
},
],
}
#多対多
例)ユーザーテーブルとスキルテーブルで確認します。
スキルテーブルにはプログラミングの言語が入っています。
あるユーザは複数のプログラミングを扱えるとします。
#Skillモデルを作成します。
$ php artisan make:model Skill -m
Model created successfully.
Created Migration: 2020_01_24_134708_create_skills_table
##skillsテーブルの作成
public function up()
{
Schema::create('skills', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('language');
$table->timestamps();
});
}
##migration実行
$ php artisan migrate
Migrating: 2020_01_24_134708_create_skills_table
Migrated: 2020_01_24_134708_create_skills_table (0.03 seconds)
##seederファイルの作成
$ php artisan make:seeder SkillsTableSeeder
Seeder created successfully.
##seederを実行する
public function run()
{
// $this->call(UsersTableSeeder::class);
// $this->call(ProfilesTableSeeder::class);
// $this->call(OrdersTableSeeder::class);
$this->call(SkillsTableSeeder::class);
}
###実行
$ php artisan db:seed
Seeding: SkillsTableSeeder
Database seeding completed successfully.
#中間テーブルuser_skillの作成
##migrationファイルの作成
$ php artisan make:migration create_user_skill_table
Created Migration: 2020_01_25_012117_create_user_skill_table
##user_skillテーブルの作成
public function up()
{
Schema::create('user_skill', function (Blueprint $table) {
$table->bigInteger('user_id')->unsigned();
$table->bigInteger('skill_id')->unsigned();
$table->primary(['user_id','skill_id']);
//外部キー制約
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
//
$table->foreign('skill_id')
->references('id')
->on('skills')
->onDelete('cascade');
});
}
##migrateの実行
##seeder関連
public function run()
{
DB::table('skill_user')->insert([
['user_id' => 1, "skill_id" => 1],
['user_id' => 1, "skill_id" => 3],
['user_id' => 2, "skill_id" => 2],
['user_id' => 2, "skill_id" => 3],
['user_id' => 3, "skill_id" => 4],
['user_id' => 4, "skill_id" => 5],
['user_id' => 5, "skill_id" => 1],
]);
}
#モデル関連の修正
##Userモデル編集
public function skills() {
return $this->belongsToMany(Skill::class);
}
##Skillモデルの編集
public function users() {
return $this->belongsToMany(User::class);
}
#tinkerで確認
$ php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman
>>> $skill = Skill::find(1);
[!] Aliasing 'Skill' to 'App\Skill' for this Tinker session.
=> App\Skill {#2980
id: 1,
language: "HTML",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
}
>>> $skill->users;
=> Illuminate\Database\Eloquent\Collection {#2981
all: [
App\User {#2984
id: 1,
name: "Enomoto",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2983
skill_id: 1,
user_id: 1,
},
},
App\User {#2988
id: 5,
name: "Sugihara",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2986
skill_id: 1,
user_id: 5,
},
},
],
}
>>>
#番外編:id以外をprimary_keyにするuserのnameで紐つける
##usersテーブルのmigrationファイルを修正
public function up()
{
Schema::create('users', function (Blueprint $table) {
// $table->bigIncrements('id');
$table->string('name')->primary();
$table->timestamps();
});
}
##profilesテーブルのmigrationファイルを修正
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('user_name');
$table->string('url');
$table->timestamps();
});
}
ポイント:テーブル名_プライマリーキー→user_name
##Userモデルを編集
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $primaryKey = "name";
protected $keyType = "string";
public $incrementing = false;
public function profile() {
return $this->hasOne(Profile::class);
}
}
###protected $primaryKey = "name";
nameカラムをプライマリーキーに設定
###public $incrementing = false;
1づつ増えていく整数にしない場合
##データベースにデータを挿入
###usersテーブルに挿入するデータ
public function run()
{
DB::table('users')->insert([
['name' => 'Enomoto','created_at' => new Datetime(),'updated_at' => new Datetime()],
['name' => 'Amano','created_at' => new Datetime(),'updated_at' => new Datetime()],
['name' => 'Shimamura','created_at' => new Datetime(),'updated_at' => new Datetime()],
['name' => 'Hirai','created_at' => new Datetime(),'updated_at' => new Datetime()],
['name' => 'Sugihara','created_at' => new Datetime(),'updated_at' => new Datetime()],
]);
}
}
###profilesテーブルにデータを挿入
public function run()
{
DB::table('profiles')->insert([
['user_name' => 'Amano','url' => "https://AmanoYasushi",'created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_name' => 'Sugihara','url' => "https://SugiharaGensei",'created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_name' => 'Enomoto','url' => "https://EnomotoRiko",'created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_name' => 'Shimamura','url' => "https://ShimamuraMayu",'created_at' => new Datetime(),'updated_at' => new Datetime()],
['user_name' => 'Hirai','url' => "https://HiraiHana",'created_at' => new Datetime(),'updated_at' => new Datetime()],
]);
}
}
##tinkerで確認
$ php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.13 — cli) by Justin Hileman
>>> $user = User::find('Amano');
[!] Aliasing 'User' to 'App\User' for this Tinker session.
=> App\User {#2980
name: "Amano",
created_at: "2020-01-22 11:54:31",
updated_at: "2020-01-22 11:54:31",
}
>>> $user->profile;
=> App\Profile {#2983
id: 1,
user_name: "Amano",
url: "https://AmanoYasushi",
created_at: "2020-01-22 11:54:31",
updated_at: "2020-01-22 11:54:31",
}
#中間テーブルへの書き込みと削除について
#attach関数を使う
##$userにidが1のユーザーを代入する。
>>> $user = User::find(1);
=> App\User {#2998
id: 1,
name: "Enomoto",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
}
#userとskillの中間テーブルに書き込む
- user_idが1、skill_idが1
- user_idが1、skill_idが2
- user_idが1、skill_idが3
にするために、$skillsに配列で1,2,3を渡す
>>> $skills = array(1,2,3);
=> [
1,
2,
3,
]
##attach関数を使って、中間テーブルに書き込む
>>> $user->skills()->attach($skills);
=> null
##中間テーブルでuser_idの1と紐ついている物を出力する。
>>> $user->skills;
=> Illuminate\Database\Eloquent\Collection {#3016
all: [
App\Skill {#2990
id: 1,
language: "HTML",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2994
user_id: 1,
skill_id: 1,
},
},
App\Skill {#3013
id: 2,
language: "CSS",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2991
user_id: 1,
skill_id: 2,
},
},
App\Skill {#3031
id: 3,
language: "javascript",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#3028
user_id: 1,
skill_id: 3,
},
},
],
}
>>>
#detachメソッドを使って、user_idが1と紐ついているカラムを削除する
>>> $user->skills()->detach();
=> 5
>>> $user = user::find(1);
=> App\User {#3015
id: 1,
name: "Enomoto",
created_at: "2020-01-25 03:15:24",
updated_at: "2020-01-25 03:15:24",
}
##user_idが1のものが削除されていることを確認する。
>>> $user->skills;
=> Illuminate\Database\Eloquent\Collection {#2987
all: [],
}
###$user = User::find('Amano');
プライマリーキーのnameをAmanoで検索
###$user->profile;
profilesテーブルからnameの"Amano"に該当する外部キーuser_nameからデータを取得