多个连接Laravel PHP

3

我有一个博客应用程序,其中有三个表格,我想查找任何搜索查询。

三个表格: posts, categories, tags

模型:

文章 (Post):

class Post extends Model
{
    public function category(){
        return $this->belongsTo('App\Category');
    }

    public function tags(){
        return $this->belongsToMany('App\Tag','post_tag','post_id','tag_id');
    }

    public function users(){
        return $this->belongsTo('App\User','author_id');
    }
}

标签:

class Tag extends Model
{
    public function posts(){
        return $this->belongsToMany('App\Post','post_tag','tag_id','post_id');
    }
}

分类:

class Category extends Model
{
    protected $table='categories';


    public function posts(){
        return $this->hasMany('App\Post');
    }
}
表结构
/*Table: posts*/
----------------

/*Column Information*/
----------------------

Field        Type              Collation        Null    Key     Default  Extra           Privileges                       Comment  
-----------  ----------------  ---------------  ------  ------  -------  --------------  -------------------------------  ---------
id           int(10) unsigned  (NULL)           NO      PRI     (NULL)   auto_increment  select,insert,update,references           
created_at   timestamp         (NULL)           YES             (NULL)                   select,insert,update,references           
updated_at   timestamp         (NULL)           YES             (NULL)                   select,insert,update,references           
title        varchar(255)      utf8_unicode_ci  NO              (NULL)                   select,insert,update,references           
body         text              utf8_unicode_ci  NO              (NULL)                   select,insert,update,references           
slug         varchar(255)      utf8_unicode_ci  NO      UNI     (NULL)                   select,insert,update,references           
category_id  int(10) unsigned  (NULL)           YES             (NULL)                   select,insert,update,references           
image_path   varchar(255)      utf8_unicode_ci  YES             (NULL)                   select,insert,update,references           
author_id    int(10) unsigned  (NULL)           NO      MUL     (NULL)                   select,insert,update,references 



/*Table: tags*/
---------------

/*Column Information*/
----------------------

Field       Type              Collation        Null    Key     Default  Extra           Privileges                       Comment  
----------  ----------------  ---------------  ------  ------  -------  --------------  -------------------------------  ---------
id          int(10) unsigned  (NULL)           NO      PRI     (NULL)   auto_increment  select,insert,update,references           
name        varchar(255)      utf8_unicode_ci  NO              (NULL)                   select,insert,update,references           
created_at  timestamp         (NULL)           YES             (NULL)                   select,insert,update,references           
updated_at  timestamp         (NULL)           YES             (NULL)                   select,insert,update,references   

/*Table: categories*/
---------------------

/*Column Information*/
----------------------

Field       Type              Collation        Null    Key     Default  Extra           Privileges                       Comment  
----------  ----------------  ---------------  ------  ------  -------  --------------  -------------------------------  ---------
id          int(10) unsigned  (NULL)           NO      PRI     (NULL)   auto_increment  select,insert,update,references           
name        varchar(255)      utf8_unicode_ci  NO              (NULL)                   select,insert,update,references           
created_at  timestamp         (NULL)           YES             (NULL)                   select,insert,update,references           
updated_at  timestamp         (NULL)           YES             (NULL)                   select,insert,update,references 

/*Table: post_tag*/
-------------------

/*Column Information*/
----------------------

Field    Type              Collation  Null    Key     Default  Extra           Privileges                       Comment  
-------  ----------------  ---------  ------  ------  -------  --------------  -------------------------------  ---------
id       int(10) unsigned  (NULL)     NO      PRI     (NULL)   auto_increment  select,insert,update,references           
post_id  int(10) unsigned  (NULL)     NO      MUL     (NULL)                   select,insert,update,references           
tag_id   int(10) unsigned  (NULL)     NO      MUL     (NULL)                   select,insert,update,references 

我所要寻找的是针对任何搜索查询,例如输入“doughnuts”,应该匹配“文章标题”、“类别名称”或“标签名称”,如果发生匹配,则应在搜索结果中显示相关的文章。 我尝试过的方法
$post = DB::table('posts')
  ->join('categories', 'posts.category_id', 'categories.id')
  ->join('blog_users', 'blog_users.id', 'posts.author_id')
  ->join('post_tag', 'posts.id', 'post_tag.post_id')
  ->join('tags', 'tags.id', 'post_tag.tag_id')
  ->select(
     'posts.*', 'blog_users.name',
     'post_tag.tag_id', 'post_tag.post_id',
     'tags.name', 'categories.name')
  ->where(function($query) use ($search) {
    $query->where('posts.title', 'LIKE', $search)
          ->orWhere('categories.name', 'LIKE', $search)
          ->orWhere('tags.name', 'LIKE', $search);
  })
  ->paginate(5);

但这似乎给我带来了重复的结果,并且效果不佳。我想知道更好的解决方案是什么?

@Lionel Chan 你尝试过使用 groupBy('id') 吗? - Gayan
@Gayan 我没有问这个问题 :) - Lionel Chan
我的错!@Lionel Chan 请原谅我。@BOTJr. 你试过 groupBy('id') 吗?看看我的答案是否符合你的需求。 - Gayan
1个回答

1
当我在查询中使用多个联接(特别是在SELECT查询中)时,我通常会实现一个数据库view来封装查询背后的逻辑。
创建如下迁移:
DB::statement("DROP VIEW IF EXISTS view_post");
DB::statement(" 
CREATE VIEW view_post
AS
SELECT 
    'posts.*', 
    'blog_users.name AS blog_users_name',
    'post_tag.tag_id', 
    'post_tag.post_id',
    'tags.name AS tags_name', 
    'categories.name AS categories_name'
    FROM posts
        INNER JOIN categories
        ON (posts.category_id = categories.id)
        INNER JOIN blog_users
        ON (blog_users.id = posts.author_id)
        INNER JOIN post_tag
        ON (posts.id = post_tag.post_id)
        INNER JOIN tags
        ON (tags.id = post_tag.tag_id)
 ");

然后制作一个像这样的模型。
class PostView extends Post { // <- To inherit properties of POST to here
    protected $table = 'view_post';
}

然后,您可以简化查询,如下:
$post = PostView::where(function ($query) use ($search) {
            return $query->orWhere('title', 'LIKE', $search)
                ->orWhere('tags_name', 'LIKE', $search)
                ->orWhere('categories_name', 'LIKE', $search);
        })
            ->groupBy('id')
            ->paginate(5);

重要的是要记住,一切都取决于情况。对我来说,这种方法比混淆我的查询更加清晰。我认为你也可以采用这种方法。谢谢。
注意:您可能需要进一步修改“视图”和“查询”以表示您想要实现的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接