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

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

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

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

Q&A

解決済

1回答

4140閲覧

【Laravel 5.8】直接のリレーションを持っていないモデルの保存をしたい

wijiwiji

総合スコア10

Laravel 5

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

0グッド

0クリップ

投稿2020/01/16 21:39

前提・実現したいこと

以下のテーブル構成において、problemモデルを新規保存したい

php

1users 2 id - integer 3 name - string 4 5drills 6 id - integer 7 user_id - integer 8 name - string 9 10problems 11 id - integer 12 drill_id - integer 13 name - string

該当のソースコード

UserとDrillのモデルは以下の通り。

php

1class User extends Authenticatable 2{ 3 public function drills() 4 { 5 return $this->hasMany('App\Drill'); 6 } 7 public function drillProblem() 8 { 9 return $this->hasManyThrough('App\Problem', 'App\Drill'); 10 } 11}

php

1class Drill extends Model 2{ 3 public function problems() 4 { 5 return $this->hasMany('App\Problem'); 6 } 7}

以下のコードを書くと、それぞれコメントアウトしたエラーが発生してしまいます。
user、drillに紐付いたproblemを保存するにはどうしたら良いでしょうか。

php

1use App\Drill; 2use App\Problem; 3use Illuminate\Support\Facades\Auth; 4 5class DrillsController extends Controller 6{ 7 public function create(Request $request) 8 { 9 $drill = new Drill; 10 $problem = new Problem; 11 12 Auth::user()->drills()->save($drill->fill($request->all())); //保存可能 13 Auth::user()->drills()->problems()->save($drill->fill($request->all())); //Call to undefined method Illuminate\Database\Eloquent\Relations\HasMany::problems() 14 Auth::user()->drillProblem()->save($drill->fill($request->all())); //Call to undefined method Illuminate\Database\Eloquent\Relations\HasOneThrough::save() 15 } 16}

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

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

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

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

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

mix-peach

2020/01/17 02:23

$request->all() は、どのような内容ですか?
wijiwiji

2020/01/17 02:33

情報不足で申し訳ございません! $request->all()は、Drill(およびProblem)登録ページのformにてsubmitした内容です。 このページでは、Drillのname、および複数のProblemのnameを登録するイメージです。 つまり、$requestには、drill_name、problem0_name、problem1_name、problem2_name,,,などが入いる予定です。
guest

回答1

0

ベストアンサー

php

1Auth::user()->drills();

これで戻ってくるのは、「user は drill を複数持ちます」というリレーション設定(hasMany)のインスタンスなので、drillのModelインスタンスではありません。

その為、Auth::user()->drills()->problems() という使い方は出来ません。(problems()を持っているのは、drillのModelインスタンスです。)

php

1Auth::user()->drillProblem();

こちらは、「user は drill 経由で、problemを複数持ちます」というリレーション設定(hasManyThrough)です。Auth::user()->drills()は、直接のリレーションを持っているので、save()することが出来ますが、Auth::user()->drillProblem()は、経由のdrillなしにはデータを持ち得ませんので、直接save()することはできません。


上記を踏まえつつ。。。

多分ちょっと難しく考えすぎなのかなと思いました。

user → problem の関係性は、drillありきで成り立つものなので、

① userに所属するdrill

② ①で作成したdrillに所属する、problem(複数)

の2手順でデータを作成すれば、自動的に user → problem の関係が出来上がります。

つまり、「直接のリレーションを持っていないモデルの保存をしたい」という処理自体は、実は必要ないのです。


私ならこんな感じにするかなという参考コードです。
(※動作検証しておりませんので、スペルミス・不具合等ありましたらご容赦を)

Modelインスタンスは最初に定義しなくても、リレーション設定を使ってデータを作成することで取得可能です。

drillの作成

php

1 2//これでuserに紐づいたdrillのModelインスタンスが戻ってきます 3$drill = Auth::user()->drills()->create(['name' => $request->input['drill_name']]); 4

problemの作成

php

1$problem_names = []; 2$idx = 0; 3 4//problemのnameがいくつ渡されるのか分からないので、とりあえず取得出来る限り保存するつもりでこんな書き方にしましたが、実際の取得した結果で上手くように調整してください。 5while($proble_name = $request->input[sprintf('problem%d_name', $idx++)]){ 6 $problem_names[] = ['name' => $proble_name ]; 7} 8 9//取得したproblem_namesを一括で保存してみます。 10//problemsの中身は、Problemのモデルインスタンスを沢山持つCollectionです。 11$problems = $drill->problems()->createMany($problem_names); 12

以上、ご参考までに。。。

投稿2020/01/17 03:28

mix-peach

総合スコア1910

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問