简化嵌套的if语句 [英] simplify nested if statements
问题描述
我正在实现搜索功能,并且基于查询参数,我使用其他类进行搜索.
I'm implementing a search functionality and based on the query parameter i use a different class to search.
class Search {
public function getResults()
{
if (request('type') == 'thread') {
$results = app(SearchThreads::class)->query();
} elseif (request('type') == 'profile_post') {
$results = app(SearchProfilePosts::class)->query();
} elseif (request()->missing('type')) {
$results = app(SearchAllPosts::class)->query();
}
}
现在,当我想搜索线程时,我有以下代码.
Now when i want to search threads i have the following code.
class SearchThreads{
public function query()
{
$searchQuery = request('q');
$onlyTitle = request()->boolean('only_title');
if (isset($searchQuery)) {
if ($onlyTitle) {
$query = Thread::search($searchQuery);
} else {
$query = Threads::search($searchQuery);
}
} else {
if ($onlyTitle) {
$query = Activity::ofThreads();
} else {
$query = Activity::ofThreadsAndReplies();
}
}
}
}
解释代码.
如果用户输入搜索词( $ searchQuery ),则使用 Algolia 进行搜索,否则直接进行数据库查询.
If the user enters a search word ( $searchQuery) then use Algolia to search, otherwise make a database query directly.
-
如果用户输入搜索词
If the user enters a search word
- 如果用户 选中了 onlyTitle 复选框 ,则使用 Thread 索引.
- 如果用户未选中 onlyTitle 复选框 ,则使用线程索引.
- Use the Thread index if the user has checked the onlyTitle checkbox
- Use the Threads index if the user hasn't checked the onlyTitle checkbox
如果用户未输入搜索词
If the user doesn't enter a search word
- 如果用户已选中 onlyTitle 复选框,则
- 获取所有线程
- 如果用户没有选中 onlyTitle 复选框 ,则获取所有线程和答复
- Get all the threads if the user has checked the onlyTitle checkbox
- Get all the threads and replies if the user hasn't checked the onlyTitle checkbox
是否有一种模式可以简化嵌套的if语句,还是应该为其中的情况创建一个单独的类
Is there a pattern to simplify the nested if statements or should i just create a separate class for the cases where
- 用户输入了搜索词
- 用户未输入搜索词
在每个类中检查用户是否已选中 onlyTitle 复选框
And inside each of those classes to check if the user has checked the onlyTitle checkbox
推荐答案
我会将此代码重构为:
保留请求参数以统一界面中的搜索方法.
Leave the request parameter to unify the search methods in an interface.
interface SearchInterface
{
public function search(\Illuminate\Http\Request $request);
}
class Search {
protected $strategy;
public function __construct($search)
{
$this->strategy = $search;
}
public function getResults(\Illuminate\Http\Request $request)
{
return $this->strategy->search($request);
}
}
class SearchFactory
{
private \Illuminate\Contracts\Container\Container $container;
public function __construct(\Illuminate\Contracts\Container\Container $container)
{
$this->container = $container;
}
public function algoliaFromRequest(\Illuminate\Http\Request $request): Search
{
$type = $request['type'];
$onlyTitle = $request->boolean('only_title');
if ($type === 'thread' && !$onlyTitle) {
return $this->container->get(Threads::class);
}
if ($type === 'profile_post' && !$onlyTitle) {
return $this->container->get(ProfilePosts::class);
}
if (empty($type) && !$onlyTitle) {
return $this->container->get(AllPosts::class);
}
if ($onlyTitle) {
return $this->container->get(Thread::class);
}
throw new UnexpectedValueException();
}
public function fromRequest(\Illuminate\Http\Request $request): Search
{
if ($request->missing('q')) {
return $this->databaseFromRequest($request);
}
return $this->algoliaFromRequest($request);
}
public function databaseFromRequest(\Illuminate\Http\Request $request): Search
{
$type = $request['type'];
$onlyTitle = $request->boolean('only_title');
if ($type === 'thread' && !$onlyTitle) {
return $this->container->get(DatabaseSearchThreads::class);
}
if ($type === 'profile_post' && !$onlyTitle) {
return $this->container->get(DatabaseSearchProfilePosts::class);
}
if ($type === 'thread' && $onlyTitle) {
return $this->container->get(DatabaseSearchThread::class);
}
if ($request->missing('type')) {
return $this->container->get(DatabaseSearchAllPosts::class);
}
throw new InvalidArgumentException();
}
}
final class SearchController
{
private SearchFactory $factory;
public function __construct(SearchFactory $factory)
{
$this->factory = $factory;
}
public function listResults(\Illuminate\Http\Request $request)
{
return $this->factory->fromRequest($request)->getResults($request);
}
}
由此得出的结论是,不要将请求包含在构造函数中,这一点非常重要.这样,您可以在应用程序生命周期中创建实例而无需请求.这有利于缓存,可测试性和模块化.我也不喜欢应用程序和请求方法,因为它们会凭空获取变量,从而降低了可测试性和性能.
The takeaway from this is it is very important to not involve the request in the constructors. This way you can create instances without a request in the application lifecycle. This is good for caching, testability and modularity. I also don't like the app and request methods as they pull variables out of thin air, reducing testability and performance.
这篇关于简化嵌套的if语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!