Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

タグ機能の更新をできるようにしたい(Laravel)

解決したいこと

Laravelで画像投稿アプリを作っています。
そこで、検索フォームに調べたいタグの名前を検索することで、その検索内容と一致するタグを持っている投稿を表示できる機能の作成をしています。
タグの作成はできたのですが、タグの更新にて以下のように内容が重複してしまいます。
スクリーンショット 2022-03-01 11.10.06.jpg
フォームから渡されたタグの中に新しいタグがあればその内容だけをDBに保存して表示するといった方法を考えていますが、うまくいきませんでした。
新しいタグを判断するといった方法以外にもわかる方がいらっしゃれば、ご教示お願いします。🙇‍♂️

開発環境

  • Macbook Pro M1
  • Laravel ver 8.82.0
  • MySQL ver 8.0.27
  • docker ver 20.10.12

該当するソースコード

tableについて

tagsテーブル

postsテーブル
+------------+-----------------+------+-----+---------+----------------+
| Field      | Type            | Null | Key | Default | Extra          |
+------------+-----------------+------+-----+---------+----------------+
| id         | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255)    | NO   |     | NULL    |                |
| body       | text            | NO   |     | NULL    |                |
| image      | varchar(255)    | NO   |     | NULL    |                |
| created_at | timestamp       | YES  |     | NULL    |                |
| updated_at | timestamp       | YES  |     | NULL    |                |
+------------+-----------------+------+-----+---------+----------------+
tagsテーブル
+------------+-----------------+------+-----+---------+----------------+
| Field      | Type            | Null | Key | Default | Extra          |
+------------+-----------------+------+-----+---------+----------------+
| id         | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| tag_name   | varchar(255)    | NO   |     | NULL    |                |
| created_at | timestamp       | YES  |     | NULL    |                |
| updated_at | timestamp       | YES  |     | NULL    |                |
+------------+-----------------+------+-----+---------+----------------+
post_tagテーブル
+------------+-----------------+------+-----+---------+----------------+
| Field      | Type            | Null | Key | Default | Extra          |
+------------+-----------------+------+-----+---------+----------------+
| id         | bigint unsigned | NO   | PRI | NULL    | auto_increment |
| post_id    | bigint unsigned | NO   | MUL | NULL    |                |
| tag_id     | bigint unsigned | NO   |     | NULL    |                |
| created_at | timestamp       | YES  |     | NULL    |                |
| updated_at | timestamp       | YES  |     | NULL    |                |
+------------+-----------------+------+-----+---------+----------------+

bladeファイル

<ul>
        @forelse ($posts as $post)
            <li>
                No.{{$post->id}}
                <a href="{{route('posts.show', $post)}}">
                    {{$post->title}}
                </a>
                <div class="tags">
                    tag:
                    @foreach ($post->tags as $tag)
                    <a href="">{{$tag->tag_name}}</a>//tagsテーブルの中にあるtag_nameの表示
                @endforeach
                </div>
                <div class="welcome_pic">
                    <img src="{{asset('storage/' . $post->image)}}">//画像の表示
                </div>
            </li>
        @empty
            <li>データありまへんわ!</li>
        @endforelse
    </ul>

コントローラー(update)

 public function update(Request $request, Post $post)
    {
        $request->validate([
            'title' => 'required|min:3',
            'body' => 'required',
        ],[
            'title.required' => 'タイトルがありません',
            'title.min' => ':min 文字以上入力してください',
            'body.required' => '本文がありません',
        ]);

        $post->title = $request->title;
        $post->body = $request->body;

        if($request->image != null)
        {
        $post->image = $request->image;
        $file = $request->file('image');
        $resized = InterventionImage::make($file)->resize(1920, null, function ($constraint) {
            $constraint->aspectRatio();
        })->save();

        //画像の保存
        Storage::put('public/' . $post->image, $resized);
        }

        // #(ハッシュタグ)で始まる単語を取得。結果は、$matchに多次元配列で代入される。
        preg_match_all('/#([a-zA-z0-90-9ぁ-んァ-ヶ亜-熙]+)/u', $request->body, $match);
        $tags = [];

        foreach($match[1] as $tag){
            $found = Tag::firstOrCreate(['tag_name' => $tag]);

            array_push($tags, $found);
        }

        $tag_ids = [];
        foreach($tags as $tag){
            $found = Tag::firstOrCreate(['tag_name' => $tag]);

            array_push($tag_ids, $tag['id']);
        }


        $post->save();
        $post->tags()->sync($tag_ids);


        return redirect()
            ->route('posts.show', $post);
    }

自分で試したこと

  • Tag::where('tag_name', $found)->exists()とし、値が存在するか
    →全て存在するとなったので、どれが新しいタグか判断できない。
      
  • firstOrCreate()updateOrCreate()とし、wasRecentlyCreatedで新しく作成されたものか判断。
    →同様に全て新しく作成されたものと表示され、判断ができない。
0

1Answer

Comments

  1. @kamotetuさんありがとうございます!
    送ってもらったURLの通りに実装してみたところ、うまく実装することができました!

Your answer might help someone💌