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

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

ただいまの
回答率

88.93%

モデルにおけるデータ記録処理の連携について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 218

mcddx330

score 14

現在構築しているwebサービスのシステムにおいて、複数テーブルをまたいだデータの保存方法に悩んでいます。

例題

あるユーザーAさんが商品Iを購入したというデータを新規で記録する場合

  • ユーザーデータが存在する
    「userテーブル.ユーザーA」
  • そのユーザーが商品を買う
    「receiptテーブル.商品IのID」
  • 購入した商品に好きなタグがつけられる
    「tagテーブル.タグ名X」、「tagテーブル.タグ名Y」・・・

といったイメージです。

ここで実際に記録する際、Laravel(Eloquent)上では次のような記述になるかと思われますが、

/* コントローラー上の動作 */

// アイテム情報取得
$item_model = Item::find('アイテムのID');

// ユーザー情報取得
$user_model = User::find('ユーザーID');

// 購入情報記録
$reciept_model = Receipt::create([
    'user_id' => $user_model->id,
    'item_id' => $item_model->id,
]);

// アイテムに対するタグ付け
$tag_model = Tag::create([
    'user_id' => $user_model->id,
    'item_id' => $item_model->id,
    'tag_value' => 'タグ名'
]);


この場合登録ごとにcreateをするのでどこか冗長的な気がします。
そこで「ユーザーは商品を買わないと好きなタグが付けられない」という事から、次のような方法を検討しています。

/* Receiptモデル上 */
protected $tag_value;

public function saveWithTag() {
    self::create([
        'user_id' => $this->user_id,
        'item_id' => $this->item_id,
    ]);
    Tag::create([
        'user_id' => $this->user_id,
        'item_id' => $this->item_id,
        'tag_value' => $this->tag_value,
    ]);
}


/* コントローラー上 */
// アイテム情報取得
$item_model = Item::find('アイテムのID');

// ユーザー情報取得
$user_model = User::find('ユーザーID');

// 購入記録とタグ付けを同時に行う(※変更点※)
$receipt_model = new Receipt();
$receipt_model->user_id = $user_model->id;
$receipt_model->item_id = $item_model->id;
$receipt_model->tag_value = 'タグ名';

$reciept_model->saveWithTag();

ここでお伺いしたいのが、上記の通り

  • 「ユーザーは商品を買わないと好きなタグが付けられない」

という点から

  • 「購入履歴モデルにはタグ付けをする責務も負わせることが出来る」

という解釈で、今回のようにその他テーブルへの(読み)書きを行うという考えは普通なのでしょうか?

もしくは

  • 「1つのモデルは1つのテーブルしか取り扱ってはいけない」

という考えの元、関係性があったとしても連携はあくまでコントローラー上など「別の適切な場所」で行うのが普通なのでしょうか?

宜しくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mikkame

    2020/01/20 14:59

    複数回に渡る同一商品の購入は想定されていますか?

    キャンセル

  • mcddx330

    2020/01/21 05:02

    はい。同一商品の購入を行った場合も新規で登録が行える(=追加登録可能)事も想定しています。
    「買う度に増える一方では?」という点についてはタグ付を行わないケースや別途編集・削除機能が存在するという見立てで問題ありません。
    あくまで複数テーブルを使用する際の記述作法についての内容です。

    キャンセル

回答 1

checkベストアンサー

0

この場合登録ごとにcreateをするのでどこか冗長的な気がします。

リレーションに対するsave/createを行う事でもう少しスマートにかけるかと思います。
関連したモデルの挿入/更新

そこで「ユーザーは商品を買わないと好きなタグが付けられない」という事から、次のような方法を検討しています

注文ごとにタグをつける事ができるなら、Receiptに直接タグ名を突っ込めば良いかと思います

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/24 13:06

    > リレーションに対するsave/createを行う事でもう少しスマートにかけるかと思います。
    なるほどリレーションの手がありましたね。元データから連携して読みに行く印象が強かったので盲点でした。

    > 注文ごとにタグをつける事ができるなら、Receiptに直接タグ名を突っ込めば良いかと思います
    こちらも考えたのですが、独立して管理するほうが都合がいいケースもあり(例自体が良いものではなかったかもしれません・・・)、あえて分けて考えるようにしていました。
    ただ上記点でも十分コードの質的に間違いが起きにくそうなので、こちらをベストアンサーにします。ありがとうございます!

    キャンセル

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

  • ただいまの回答率 88.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る