【Laravel】テーブルのデータ操作方法について
受付中
回答 2
投稿
- 評価
- クリップ 1
- VIEW 1,052
開発環境
Laravel 5.6
分からないこと
Laravelを使用した掲示板プログラムを、こちらのサイトを参考にして作成しているのですが、
そこで行われている、テーブルのデータ操作方法が、ぼんやりと理解できるのですが明確に自分の中で言語化できません。
その方法を流用して機能を追加したいと考えているため、処理の流れを自分の中できちんと理解したいです。
具体的には、postsとcommentsという2つのテーブルがあり、
モデルであるPost.phpでは、
public function comments()
{
return $this->hasMany('App\Comment');
}
Comment.phpでは、
public function post()
{
return $this->belongsTo('App\Post');
}
という記述があります(「postsテーブルとcommentsテーブルが1対多の関係である」と定義していると思っています)
その上で、Controllerにて、postテーブルの値を取得し全件表示するために、
public function show($post_id)
{
$post = Post::findOrFail($post_id);
return view('posts.show', [
'post' => $post,
]);
}
とやっています。
この時、$postの中には、postsテーブルの中身とcommentsテーブルの中身が全て格納されるのだろうと思うのですが、
なぜ2つのテーブルから一気にデータを取得できるのか、が上手く言語化できません。
$post = Post::findOrFail($post_id);
で、Postモデルを使用してpostsテーブルの値を取得している一方、Commentモデルを使用している様子がないのは、
先述のhasMany('App\Comment'); によって、PostモデルとCommentモデルが紐づいているのでCommentモデルをわざわざ使うことなくcommentsテーブルの値を取得できる、という理解で正しいでしょうか。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーー
また、postsテーブルの値を削除する関数が、
public function destroy($post_id)
{
$post = Post::findOrFail($post_id);
\DB::transaction(function () use ($post) {
$post->comments()->delete();
$post->delete();
});
return redirect()->route('top');
}
と定義されており、結果として、投稿データとそれに紐づくコメント全てがテーブルからdeleteされるのですが、
$post->comments()->delete();
の、comments()とは、Postモデルで定義されているcommentsメソッドのことでしょうか。
$postの値をcomments関数に渡して、deleteを実行している、ということでしょうか。ここが上手く言語化できません。
変数->関数 というアロー演算子の使い方は、公式ドキュメントでも見当たらず、他にサンプルがないので処理内容が分かりません。
長文になってしまい恐縮ですが、どなたかお時間のある方、サイトをご参照のうえ上記内容について、合っている/そうじゃない・正しくはこう、といったアドバイスいただけないでしょうか。
宜しくお願いいたします。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
一部にのみ回答する形になります。
前提として
利用者が頑張って言語化しようとしなくても、書いたとおりに動くだけです。動いている結果が全てということですね。
もしドキュメントを読んでも納得しないのであればコアソースをしっかり追ってみることです。そのほうが他人に説明を受けるよりも何倍も理解が深まりますし、より効果的な使い方ができます。
$postの中には、postsテーブルの中身とcommentsテーブルの中身が全て格納されるのだろうと思うのですが、
なぜ2つのテーブルから一気にデータを取得できるのか、が上手く言語化できません
findOrFail()およびfind()の仕様をドキュメントで確認してください。
$post->comments()->delete();
の、comments()とは、Postモデルで定義されているcommentsメソッドのことでしょうか。
$postの値をcomments関数に渡して、deleteを実行している、ということでしょうか。ここが上手く言語化できません。
変数->関数 というアロー演算子の使い方は、公式ドキュメントでも見当たらず、他にサンプルがないので処理内容が分かりません。
ここで見るべきは「変数が保持しいている情報」となります。
おそらくどこかしらでnewなりしているのでしょうが(そのコードが提示されてないので私にはわかりません)、実際に持っているのはオブジェクトになります。
dd()なりdump()なりで確認してみると保持している情報を確認することができます。
オブジェクトが保持しているメソッドなりプロパティは利用可能です。
アロー演算子が更に重ねてあるのは「その結果をもって更に実行する」ことになります。
つまり、$postもオブジェクトだし$post->comments()もオブジェクトを返しているということになります。
LaravelというよりPHPのオブジェクト指向部分になるので、確認すべきはPHPマニュアルと思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
変数->関数 というアロー演算子の使い方は、公式ドキュメントでも見当たらず、他にサンプルがないので> 処理内容が分かりません。
変数->関数という考え方だと余計に混乱すると思います。ここはPHPにおける、オブジェクト指向のインスタンスとメソッドの関係です。LaravelはあくまでPHPを使ったフレームワークなので、公式マニュアルもPHPの記述ルールを熟知している前提での補足説明にとどまっています。したがって、この辺りはPHPのオブジェクト指向を参照した方がいいでしょう。公式ページもありますが、自分はこのページで勉強しました。
なぜ2つのテーブルから一気にデータを取得できるのか、が上手く言語化できません。
ここはリンク先のページのDBテーブル設計を見たらわかると思いますが、postsマスタのidとcommentsトランザクションのuser_idが双方紐付いているからです。hasMany()
は1対多の関係、対してbelongsTo
は多対1の関係になっています。これをわかりやすく言えば
一つの投稿(posts)には複数の記事(comments)を持っているということです。そのidを紐付けておかないと、記事はバラバラになってしまい、うまく整理することができないですね。
、comments()とは、Postモデルで定義されているcommentsメソッドのことでしょうか。
$postの値をcomments関数に渡して、deleteを実行している、ということでしょうか。ここが上手く言語化できません。
destoryメソッドにある\DB::transaction(function () use ($post) {…}
はPHPにおけるクロージャの記述です。クロージャは説明するとややこしくなりますが、平たく言えば同じidを持つデータに対し、同じ処理を繰り返す仕組みです。したがって、特定の投稿idを持つ記事全部に対して、記事がなくなるまでDBにおけるdelete文処理を繰り返すことになります。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.10%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2019/11/06 23:17
仰る通り、こう書けばこう動く、というのは分かったのですが、「なぜこう書けばこう動くんだ」という、裏側では何が行われているんだ、が分からない状態になっており、
機能を流用するにあたってそれでは良くない、と考えた次第です。
findOrFail()については、引数の変数の値を条件にしてテーブルに対して何らかのクエリ処理を指示するか、できなかったらできなかったということを返すか、という事は分かりました。
ただ、無事クエリ処理を実行できた結果は、配列で返ってくるのか別な形で返ってくるのか、という所は公式ドキュメントにも載っておらず、理解はふわっとした状態です。
dd($post)とやると、Collectionなるものに様々な情報が配列の形で格納されていました。該当の投稿にはコメントが2つ付いている状態なのですが、それぞれのコメントのID、本文、作成日なども格納されていることが確認できました。
これは、$postというオブジェクトの詳細を見ている、という行為になるのでしょうか?
$post = Post::findOrFail($post_id);
\DB::transaction(function () use ($post) {
$post->comments()->delete();
については、
delete()の使い方が、以下のように公式ドキュメントに記述されておりまして、
$flight = App\Flight::find(1);
$flight->delete();
取得した値のうち、postsテーブルと紐づくcommentsテーブル上の値をdeleteする処理だ、ということだと考えています。
ただ、
$post->comments()->delete();
は、$post = new Post; とやっていないのにも関わらずpostクラスで定義されたcommentsメソッドを使用しているように見えるのがどうにもモヤモヤします!なぜなのでしょうか・・・?
何か、ご教示いただけることがありましたらぜひ、よろしくお願いいたします。
2019/11/06 23:24
となると、やはり他人の説明を受けたところで他人ごとになってしまうので、自身でコアソースを読み進めた方が良いでしょう。