質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

1回答

633閲覧

laravel モデルのリレーションについて

neginattofan

総合スコア66

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

1グッド

0クリップ

投稿2020/03/13 05:18

編集2020/03/19 04:02

初めてモデルのリレーションについて触れました。
laravel5.8です

1対多の概念はおそらく理解し、あるユーザーはいくつもドリルを作ることができるようにしました。

User

1id 2name

Drill

1コード 2id 3user_id 4title 5problem0 6problem1 7... 8problem9

2つのモデルの扱い方はなんとなく理解したので、この2つのモデルをもとに4つのモデルでリレーションを作りたいです。
User:Drill 1:多
Category:Drill: 1:多
Problem:Drill 1:1

それぞれのmysqlテーブルのプロパティは

users

1id 2name

drills

1id 2title 3user_id 4category_id

category

1id 2category_name

problems

1id 2drill_id 3problem0 4problem1 5... 6problem9

です。

モデルは

User

1<?php 2 3namespace App; 4 5use Illuminate\Notifications\Notifiable; 6use Illuminate\Contracts\Auth\MustVerifyEmail; 7use Illuminate\Foundation\Auth\User as Authenticatable; 8 9class User extends Authenticatable 10{ 11 use Notifiable; 12 13 /** 14 * The attributes that are mass assignable. 15 * 16 * @var array 17 */ 18 protected $fillable = [ 19 'name', 'email', 'password', 20 ]; 21 22 /** 23 * The attributes that should be hidden for arrays. 24 * 25 * @var array 26 */ 27 protected $hidden = [ 28 'password', 'remember_token', 29 ]; 30 31 /** 32 * The attributes that should be cast to native types. 33 * 34 * @var array 35 */ 36 protected $casts = [ 37 'email_verified_at' => 'datetime', 38 ]; 39 40 public function drills(){ 41 return $this->hasMany('App\Drill'); 42 } 43}

Drill

1<?php 2 3namespace App; 4 5use Illuminate\Database\Eloquent\Model; 6 7class Drill extends Model 8{ 9 // protected $fillable = ['title', 'category_name', 'problem0','problem1','problem2','problem3','problem4','problem5','problem6','problem7','problem8','problem9']; 10 protected $fillable = ['title']; 11 12 public function user(){ 13 return $this->belongsTo('App\User'); 14 } 15 16 17 public function category(){ 18 return $this->belongsTo('App\Category'); 19 } 20 21 22 public function problem(){ 23 return $this->hasOne('App\Problems'); 24 } 25} 26

Category

1<?php 2 3namespace App; 4 5use Illuminate\Database\Eloquent\Model; 6 7class Category extends Model 8{ 9 protected $fillable = ['category_name']; 10 11 12 public function drills(){ 13 return $this->hasMany('App\Drill'); 14 } 15 16}

Problem

1<?php 2 3namespace App; 4 5use Illuminate\Database\Eloquent\Model; 6 7class Problem extends Model 8{ 9 protected $fillable = ['problem0','problem1','problem2','problem3','problem4','problem5','problem6','problem7','problem8','problem9']; 10 11 12 public function drill(){ 13 return $this->belongsTo('App\Drill'); 14 } 15} 16

このような感じです。

アプリケーションで行うCRUD処理は4つのテーブルが常に関係しているようにします。(drillsテーブルにはusersテーブル、categoryテーブルとそれぞれ紐づくuser_id,category_idを与え、drillsテーブルと紐づくdrill_idをproblemsテーブルに与えています。)

二つのモデルだったときのCRUD処理は、二つのusersテーブルとdrillsテーブルが常に関係しているようにして

Auth::user()->drills()->save($drill->fill($request->all())); //登録 Auth::user()->drills()->find($id)->delete(); //消去

で成功しました. 

4つのモデルを全て紐付けると、どのようなコードを実行すればいいか分かりません。
例えば、drillのタイトル(title)と、カテゴリー名(category_name)と、問題一覧(problem1,probelm2,...probelm9)と、登録するユーザー名(user_name)を関連づけて登録する場合
上記の4つのモデルで、

Auth::user()->drills()->save($drill->fill($request->all())); //登録

を行うと、General error: 1364 Field 'category_id' doesn't have a default value (SQL: insert into drills (title, user_id, updated_at, created_at) values (aaa, 1, 2020-03-19 03:01:58, 2020-03-19 03:01:58))

が出てしまいます。
おそらくcategory_idも紐付けて登録しないといけないのですが、どういったコードで修正できるか分かりません。

よろしくお願いします。

s.k👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/03/13 06:34

それぞれのModel の実装を提示してください。それがどこまでできているのかで回答が変わってしまいますので。
neginattofan

2020/03/13 06:50

質問を修正しました。よろしくお願いします。
退会済みユーザー

退会済みユーザー

2020/03/13 06:58 編集

// エラー というコメントはなんの意味があってつけているんですか?
退会済みユーザー

退会済みユーザー

2020/03/13 06:59

あと、リレーションのメソッド名、単数形、複数形には意味があるので、混同せず使い分けましょう。
neginattofan

2020/03/13 07:04

2つのモデルから4つのモデルに分割しようとして追加したコードがエラーだったので付けました。
neginattofan

2020/03/13 07:06

その通りですね、今後注意します。
退会済みユーザー

退会済みユーザー

2020/03/13 07:06

何をした時に、どんなエラーが発生したのかを具体的に書いてくれないと、質問を読む人に伝わりませんよ。
退会済みユーザー

退会済みユーザー

2020/03/13 07:15

> その通りですね、今後注意します。 承知しました。では、今後回答します。
neginattofan

2020/03/13 09:10

お手数ですが、よろしくお願いします。
退会済みユーザー

退会済みユーザー

2020/03/13 09:22

回答が欲しいのであれば、指摘された部分を修正して欲しい。 前提条件に間違いがあるままでは回答のしようがありませんし、ナレッジベースとしてのサイトの意義が崩壊しますし、同じ問題を抱えた方の指針にもなりません。回答する立場としては、目の前の質問者だけのためでなく、同じ問題に直面した方の為にもなる回答を心がけているつもりですので、よろしくです。
neginattofan

2020/03/13 09:36

修正しました。漏れがないとは思いますが。。お手数かけてすみません。。
退会済みユーザー

退会済みユーザー

2020/03/13 09:38

修正した感じを見ると、Laravelの設計思想を理解していないようですね。 それを含めて、回答しましょう。
neginattofan

2020/03/15 02:00

CategoryモデルとUserモデルのみdrills()に修正しました。
neginattofan

2020/03/19 06:59 編集

protected $fillable = ['title', 'category_id'];を試してみましたが、同じエラーが出てしまいました。 上の質問に書いたように、4つのモデルにmigrateする前にもuser_idをdrillsテーブルに与えていながら、Drillモデルの中のDrillクラスのなかでprotected $fillable = [title,...,problem9]とだけ書いていました。user_idは$fillableに入れてませんでしたが、二つのモデルを紐づけてCRUD処理できました。 もしcategory_idがfillableにあるべきなら、user_idもfillableにないと同じエラーが出てしまうと思うのですが、このようなエラーは出ませんでした。
退会済みユーザー

退会済みユーザー

2020/03/19 06:57

君はいったい誰に対して何を書いておるのだ?
guest

回答1

0

ベストアンサー

リレーションについて、belongsTo, hasOne, hasMany, belongsToMany は特に使われるものなのでしっかり理解しておこう。

上記のうち、belongsTo, hasOne はリレーション先から 一つのモデル を取得できるので、メソッド名は単数形で書くべき。

一方、hasMany, belongsToMany複数のモデル を取得するものなので、複数形で定義すべき。

例えば、Categoryモデルであれば、drills() であるべきだ。

php

1class Category extends Model 2{ 3 protected $fillable = ['category_name']; 4 5 public function drills() 6 { 7 return $this->hasMany('App\Drill'); 8 } 9} 10

まずは、この説明をもとにして、各モデルを修正して欲しい。


そこでDrillをDrill,Category, Problemという3つのモデルに分割して、全部で4つのモデルをリレーションできるかがよく理解できません。

この質問に対しては、上記の回答で十分だと思うが、

insertした時や、データをmysqlからselectする時にそれぞれの関係を保ったまま扱いたい

具体性がなくて何を回答すればいいのかに困る。

たとえば、「Drillの一覧ページを作成す流場合に、カテゴリーを取得して表示したい」という具合に。


エラーというコメントは4つのモデルにしようと追加してダメだった部分

回答者にとってはこれも全く意味不明だ。

どうダメだったのかも書かれていないし、どういう状態から変更してどうダメだったかわからないので、スルーするしかない一文だ。


php

1<?php 2 3namespace App; 4 5use Illuminate\Database\Eloquent\Model; 6 7class Drill extends Model 8{ 9 protected $fillable = ['title', 'category_id']; // category_id が入っていない 10 11 public function user(){ 12 return $this->belongsTo('App\User'); 13 } 14 15 16 public function category(){ 17 return $this->belongsTo('App\Category'); 18 } 19 20 21 public function problem(){ 22 return $this->hasOne('App\Problems'); 23 } 24}

投稿2020/03/13 09:45

編集2020/03/19 04:48
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

neginattofan

2020/03/19 07:03

ありがとうございます。試してみましたが、同じエラーが出てしまいました。 上の質問に書いたように、4つのモデルにmigrateする前にもuser_idをdrillsテーブルに与えていながら、Drillモデルの中のDrillクラスのなかでprotected $fillable = [title,...,problem9]とだけ書いていました。user_idは$fillableに入れてませんでしたが、二つのモデルを紐づけてCRUD処理できました。 もしcategory_idがfillableにあるべきなら、user_idもfillableにないと同じエラーが出てしまうと思うのですが、このようなエラーは出ませんでした。
退会済みユーザー

退会済みユーザー

2020/03/19 07:08

エラーが出るたびに他人を頼っているようですが、dd() や dump() を使ってデバッグはしていないのでしょうか?
neginattofan

2020/03/19 07:59

デバッグはしていますが、解決方法として教えていただいた方法だけでは問題が解決できないため、コメントさせていただきました。
退会済みユーザー

退会済みユーザー

2020/03/19 08:19

暇な時に回答するつもりではいますが、お急ぎではないでしょうし、それまではご自身で調査ください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問