질문을 삭제하지 말아주세요.!
 
1
0
-1

코드 중 $query = $slug ? \App\Tag::whereSlug($slug)->firstOrFail()->articles() : new \App\Article;

위와 같이 쿼리를 만들면 한개의 tag에 해당하는글을 가져오잖아요?

예를 들어 "라라벨" tag를 선택하면 라라벨 tag가 달린글을 가져오죠 그렇다면,

복수의 tag를 선택했을때 복수의 글을 가져오는법이 있을까요?


아래와 같이 컬럼을 하나더 추가해서 해봤는데요 안되더라구요...흠.. 이해가 많이 부족한거같아요..

$query = $slug ? \App\Tag::whereCate($slug)->get()->articles() : new \App\Article;


예로 "라라벨","서버"의 tag 선택해서 서치 하면 둘다 해당하는 tag의 글을 가져오게 하고 싶은데요.

예초에 제가 잘못생각하고 있는건지, 전혀 ㅜㅠ 진행이 안되고있습니다..


제가 말주변이 없어서 좀 어렵게 설명한거같은데요. 근본적으로 대분류 -> 중분류에 따른 글을 보여주고 싶은데요.. 책 내용을 토대로 글을 자동으로 가져오게 하는게 목표인데.. 예초에 제가 생각하는 접근이 잘못된건지 어렵네요..! 그래도 하나씩 풀어보려고 노력 중입니다.. 글 읽어주셔서 감사합니다..ㅠ

    CommentAdd your comment...

    2 answers

    1.  
      1
      0
      -1

      엘로퀀트를 쓰려면 아래 2)번과 같이 하면 됩니다. 다만, 쿼리빌더가 만든 SQL 쿼리가 굉장히 비효율적입니다.


      1) 조인 이용

      App\Article::select('articles.*')
          ->join('article_tag', 'articles.id', '=', 'article_tag.article_id')
          ->join('tags', 'article_tag.tag_id', '=', 'tags.id')
          ->whereIn('tags.name', ['서버', '라라벨'])
          ->get();
      
      select `articles`.* from `articles` inner join `article_tag` on `articles`.`id` = `article_tag`.`article_id` inner join `tags` on `article_tag`.`tag_id` = `tags`.`id` where `tags`.`name` in ('서버', '라라벨') and `articles`.`deleted_at` is null;
      
      id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	SIMPLE	articles	NULL	ALL	PRIMARY	NULL	NULL	NULL	10	10.00	Using where
      1	SIMPLE	article_tag	NULL	ref	article_tag_article_id_foreign,article_tag_tag_id_foreign	article_tag_article_id_foreign	4	myapp.articles.id	1	100.00	NULL
      1	SIMPLE	tags	NULL	eq_ref	PRIMARY	PRIMARY	4	myapp.article_tag.tag_id	1	40.00	Using where


      2) 엘로퀀트 관계 이용

      $articles = App\Article::whereHas('tags', function ($query) {
          $query->whereIn('name', ['서버', '라라벨']);
      })->get();
      
      select * from `articles` where exists (select * from `tags` inner join `article_tag` on `tags`.`id` = `article_tag`.`tag_id` where `article_tag`.`article_id` = `articles`.`id` and `name` in ('서버', '라라벨')) and `articles`.`deleted_at` is null;
      
      id	select_type	table	partitions	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	PRIMARY	articles	NULL	ALL	NULL	NULL	NULL	NULL	10	10.00	Using where
      2	DEPENDENT SUBQUERY	article_tag	NULL	ref	article_tag_article_id_foreign,article_tag_tag_id_foreign	article_tag_article_id_foreign	4	myapp.articles.id	1	100.00	NULL
      2	DEPENDENT SUBQUERY	tags	NULL	eq_ref	PRIMARY	PRIMARY	4	myapp.article_tag.tag_id	1	40.00	Using where
        CommentAdd your comment...
      1.  
        1
        0
        -1
        GET /articles?tags=서버,라라벨
        또는 
        GET /articles?tags[]=서버&tags[]=라라벨

        과 같이 API 엔드포인트를 만들고 요청을 받으면 아래와 같이 됩니다.

        explode(',', Request::input('tags')); // ["서버","라라벨"]
        Request::input('tags'); // ["서버","라라벨"]

        요청을 파싱했으면 쿼리를 만들면 됩니다.

        // Article, Tag 관계가 one to many라면,
        Article::join('tags', 'articles.tag_id', '=', 'tags.id')
            ->whereIn('tags.name', ['서버', '라라벨'])
            ->get();
        
        
        // Article, Tag 관계가 many to many라면,
        Article::join('article_tag', 'articles.id', '=', 'article_tag.article_id')
            ->join('tags', 'article_tag.tag_id', '=', 'tags.id')
            ->whereIn('tags.name', ['서버', '라라벨'])
            ->get();

        검증없이 쓴거라 틀릴 수도 있는데요. 혹시 틀렸다면, 문서를 좀 더 참고해서 고쳐서 쓰시면 될 듯 합니다.

        Join Query를 이용하지 않고, Eloquent Relation을 쓰는 방법도 있는데요, 공식 문서를 참고해주세요.

        1. 문병철

          답변 정말 감사드립니다.

          요청이 와서 리퀘스트에서 나눠서 넣는거까지는 알겠습니다.

          그럼 글을 불러올때

           $query = $slug ? \App\Tag::whereSlug($slug)->firstOrFail()->articles() : new \App\Article;
          관계는 belongtomany 구요
          $query = $slug ? Article::join('article_tag', 'articles.id', '=', 'article_tag.article_id')
              ->join('tags', 'article_tag.tag_id', '=', 'tags.id')
              ->whereIn('tags.name', ['서버', '라라벨'])
              ->get(); : new \App\Article 
          
          
          이렇게 하면되나요?
          조금 테스트 해봤는데요 
          조인 쿼리를 이용해서 가져오는 방식은 이해했습니다.
          엘리퀀트 방식으로 가져와보고 싶은데요
          
          
          괜찮으시다면 api 어느 부분을 보는게 좋을지 조언좀 부탁드립니다..^^;;
        CommentAdd your comment...