laravel - 为“搜索引擎”构建代码的方法
问题描述
我目前正在整理一些代码,允许用户以多种方式搜索活动表(即,如果选择了标题复选框)我觉得我的代码看起来有点乱,所以我想来堆栈溢出并问大家什么是让这段代码更优雅的最好方法吗?我只是在寻找改进的方法,拥有更易读的代码,并为其提供更好的结构。
if (request('name')){
$name = request('name');
$user = User::where('name', $name)->firstOrFail();
if (request('title') == 1) {
$activities = Activity::with('activity')->where('user_id', $user->id)->whereHas('thread', function ($query) use ($search, $user) {
$query->where('threads.user_id', '=', $user->id)
->where('threads.title', 'LIKE', '%' . $search . '%');
})->get();
dd($activities);
} else {
$activities = Activity::with('activity')->where('user_id', $user->id)->whereHas('thread', function ($query) use ($search, $user) {
$query->where('threads.user_id', '=', $user->id)
->where('threads.title', 'LIKE', '%' . $search . '%')
->orWhere('threads.body', 'LIKE', '%' . $search . '%');
})->orWhereHas('reply', function ($query) use ($search, $user) {
$query->where('replies.user_id', '=', $user->id)
->where('replies.body', 'LIKE', '%' . $search . '%');
})->get();
dd($activities);
}
} else {
if (request('title') == 1) {
$activities = Activity::with('activity')->where('user_id', $user->id)->whereHas('thread', function ($query) use ($search, $user) {
$query->where('threads.title', 'LIKE', '%' . $search . '%');
})->get();
dd($activities);
} else {
$activities = Activity::with('activity')->whereHas('thread', function ($query) use ($search) {
$query->where('threads.body', 'LIKE', '%' . $search . '%')
->orWhere('threads.title', 'LIKE', '%' . $search . '%');
})->orWhereHas('reply', function ($query) use ($search) {
$query->where('replies.body', 'LIKE', '%' . $search . '%');
})->get();
}
}
谢谢!
解决方案
您可以使用查询构建器when
和unless
方法,并在模型中定义一些查询范围,以便最终结果看起来像这样
$user = request('name') ? User::where('name', $name)->firstOrFail() : null;
$title = request('title') == 1;
$activities = Activity::with('activity')->search($search, $user, $title)->get();
# Activity model
public function scopeSearch(Builder $query, ?$search = null, ?User $user = null, bool $title = false)
{
if (!$search)
return $query;
else
return $query->when($user, fn($q) => $q->where('user_id', $user->id))
->whereHas('thread', fn($thread) => $thread->search($search, $user))
->unless($title, fn($q) => $q->orWhereHas('reply', fn($reply) => $reply->search($search, $user)));
}
# Thread model
public function scopeSearch(Builder $query, ?string $search = null, ?User $user = null)
{
if (!$search)
return $query;
else
return $query->when($user, fn($q) => $q->where('threads.user_id', $user->id))
->where(fn($q) => $q->where('threads.title', 'LIKE', "%$search%")
->orWhere('threads.body', 'LIKE', "%$search%"));
}
# Reply model
public function scopeSearch(Builder $query, ?string $search = null, ?User $user = null)
{
if (!$search)
return $query;
else
return $query->when($user, fn($q) => $q->where('replies.user_id', $user->id))
->where('replies.body', 'LIKE', "%$search%");
}
范围基本上是可重用的查询。您可以在全局级别(适用于所有模型)或本地级别(这就是我在这里所做的)定义它们。
有了它们,我几乎将所有与查询相关的逻辑都移到了模型中,但是如果您愿意,您仍然可以将其全部写入控制器中。
使用我定义的范围,
$activities = Activity::with('activity')
// call Activity Model's search scope
->search($search, $user, $title)
->get();
翻译成
$activities = Activity::with('activity')
->when($user, fn($q) => $q->where('user_id', $user->id))
// call Thread model's search scope in whereHas('thread', ...) closure
->whereHas('thread', fn($thread) => $thread->search($search, $user))
// call Reply model's search scope in whereHas('reply', ...) closure
->unless($title, fn($q) => $q->orWhereHas('reply', fn($reply) => $reply->search($search, $user)))
->get();
这反过来又转化为
$activities = Activity::with('activity')
->when($user, fn($q) => $q->where('user_id', $user->id))
->whereHas('thread', function ($thread) use ($search, $user) {
$thread->when($user, fn($q) => $q->where('threads.user_id', $user->id))
->where(fn($q) => $q->where('threads.title', 'LIKE', "%$search%")
->orWhere('threads.body', 'LIKE', "%$search%"));
})
->unless($title, fn($q) => $q->orWhereHas('reply', function ($reply) use ($search, $user) {
$reply->when($user, fn($q) => $q->where('replies.user_id', $user->id))
->where('replies.body', 'LIKE', "%$search%");
}))
->get();
此时$title
可以内联变量。->unless(request('title') == 1, ...)
推荐阅读
- java - 无法在春季应用程序中使用招摇
- angular - 在带有角度的http调用期间动画按钮单击
- ios - WatchConnectivity:didReceiveApplicationContext 永远不会被调用,尽管上下文已更新
- java - 单词 Aspose 中的条件块 (<
我正在使用 word 中的 mailmerge 创建一个 word 文档,我需要根据条件变量显示一个词块:
<<if [var]>> show text <</if>>
我正在构建 json 对象以在 java 中传递一个 word 文档,例如:
<
- sql-server - 带有表变量的消息 8152
- java - 如何获取 X 列并遍历其所有行?
- asp.net-mvc - C# 静态类 HtmlHelper 不是线程安全的
- tensorflow-hub - 无法使用 Tensorflow_hub 访问 URL
- rest - 行级安全性 (RLS) 可以在 Power BI 中以编程方式应用吗?
- c# - 无法加载文件或程序集 - 发布解决方案的程序集版本错误