我有一个博客应用程序,它有三个表,我想为任何搜索查询查看这些表。
三个表:posts
,categories
,tags
。
模型:
帖子:
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 title
或 category name
或 tag name
,如果任何匹配发生在与之相关的帖子中,则应显示在搜索结果中。
我尝试过的
$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);
但这似乎给了我重复的结果并且效果不佳。
我想知道这个问题的更好解决方案吗?
最佳答案
当我发现自己在一个查询中使用多个连接时(特别是在 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);
重要的是要记住,这完全取决于具体情况。 对于我的站来说,这是一种更简洁的方法,而不是混淆我的查询。我想你也可以采用这种方法。谢谢。
注意:您可能需要进一步修改 view
和 query
以表示您要实现的目标。
关于php - 多个连接 laravel php,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41539362/