Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/254.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 简化嵌套的if语句_Php_Laravel - Fatal编程技术网

Php 简化嵌套的if语句

Php 简化嵌套的if语句,php,laravel,Php,Laravel,我正在实现一个搜索功能,并根据查询参数使用不同的类进行搜索 class Search { public function getResults() { if (request('type') == 'thread') { $results = app(SearchThreads::class)->query(); } elseif (request('type') == 'profile_post') {

我正在实现一个搜索功能,并根据查询参数使用不同的类进行搜索

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();
     }

}
现在,当我想搜索线程时,我有以下代码

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进行搜索,否则直接进行数据库查询

  • 如果用户输入搜索词

  • 如果用户选中了onlyTitle复选框,则使用线程索引
  • 如果用户未选中“仅线程”复选框,则使用“线程”索引
  • 如果用户未输入搜索词

  • 如果用户选中了onlyTitle复选框,则获取所有线程
  • 如果用户未选中onlyTitle复选框,则获取所有线程和回复
是否有一种模式可以简化嵌套的if语句,或者我应该为以下情况创建一个单独的类:

  • 用户已输入搜索词
  • 用户尚未输入搜索词
  • 并在每个类中检查用户是否选中了onlyTitle复选框

    class Search 
    {
         public function __construct(){
                 $this->strategy = app(SearchFactory::class)->create();
             }
    
            public function getResults()
            {
                 return $this->strategy->search();
             }
    }
    
    其中,在AlgoliaSearchFactory中创建的类是algolia聚合器,因此可以对这些类中的任何一个调用search方法

    像这样的东西会让它更干净还是更糟


    现在我有一些策略,这些策略对我来说太难了。

    我曾尝试为您实现一个好的解决方案,但我不得不对代码做出一些假设

    我将请求与构造函数逻辑解耦,并给搜索接口一个请求参数。这使得意图比使用Request函数从稀薄的空气中提取请求更清晰

    final class SearchFactory
    {
        private ContainerInterface $container;
    
        /**
         * I am not a big fan of using the container to locate the dependencies.
         * If possible I would implement the construction logic inside the methods.
         * The only object you would then pass into the constructor are basic building blocks,
         * independent from the HTTP request (e.g. PDO, AlgoliaClient etc.)
         */
        public function __construct(ContainerInterface $container)
        {
            $this->container = $container;
        }
    
        private function databaseSearch(): DatabaseSearch
        {
            return // databaseSearch construction logic
        }
    
        public function thread(): AlgoliaSearch
        {
            return // thread construction logic
        }
    
        public function threads(): AlgoliaSearch
        {
            return // threads construction logic
        }
    
        public function profilePost(): AlgoliaSearch
        {
            return // thread construction logic
        }
    
        public function onlyTitle(): AlgoliaSearch
        {
            return // thread construction logic
        }
    
        public function fromRequest(Request $request): SearchInterface
        {
            if ($request->missing('q')) {
                return $this->databaseSearch();
            }
    
            // Fancy solution to reduce if statements in exchange for legibility :)
            // Note: this is only a viable solution if you have done correct http validation IMO
            $camelCaseType = Str::camel($request->get('type'));
            if (!method_exists($this, $camelCaseType)) {
                // Throw a relevent error here
            }
    
            return $this->$camelCaseType();
        }
    }
    
    // According to the code you provided, algoliasearch seems an unnecessary wrapper class, which receives a search interface, just to call another search interface. If this is the only reason for its existence, I would remove it
    final class AlgoliaSearch implements SearchInterface {
        private SearchInterface $search;
    
        public function __construct(SearchInterface $search) {
            $this->search = $search;
        }
    
        public function search(Request $request): SearchInterface {
            return $this->search->search($request);
        }
    }
    

    我也不确定搜索类的意义。如果它只是有效地将搜索方法重命名为getResults,我不确定重点是什么。这就是为什么我省略了它。

    我不得不写下所有这些,以使问题变得易懂

    SearchFactory获取所有必需的参数,并根据这些参数调用AlgoliaSearchFactoryDatabaseSearchFactory以生成将返回的最终对象

    class SearchFactory
    {
        protected $type;
        protected $searchQuery;
        protected $onlyTitle;
        protected $algoliaSearchFactory;
        protected $databaseSearchFactory;
    
        public function __construct(
            $type,
            $searchQuery,
            $onlyTitle,
            DatabaseSearchFactory $databaseSearchFactory,
            AlgoliaSearchFactory $algoliaSearchFactory
        ) {
            $this->type = $type;
            $this->searchQuery = $searchQuery;
            $this->onlyTitle = $onlyTitle;
            $this->databaseSearchFactory = $databaseSearchFactory;
            $this->algoliaSearchFactory = $algoliaSearchFactory;
        }
    
        public function create()
        {
            if (isset($this->searchQuery)) {
                return $this->algoliaSearchFactory->create($this->type, $this->onlyTitle);
            } else {
                return $this->databaseSearchFactory->create($this->type, $this->onlyTitle);
            }
        }
    }
    
    基于从搜索工厂传递的类型onlyTitle参数的数据库搜索工厂返回一个对象,该对象是获得结果所需使用的最终对象

    class DatabaseSearchFactory
    {
        public function create($type, $onlyTitle)
        {
            if ($type == 'thread' && !$onlyTitle) {
                return app(DatabaseSearchThreads::class);
            } elseif ($type == 'profile_post' && !$onlyTitle) {
                return app(DatabaseSearchProfilePosts::class);
            } elseif ($type == 'thread' && $onlyTitle) {
                return app(DatabaseSearchThread::class);
            } elseif (is_null($type)) {
                return app(DatabaseSearchAllPosts::class);
            }
        }
    }
    
    与DatabaseSearchFactory相同的逻辑

    class AlgoliaSearchFactory
    {
        public function create($type, $onlyTitle)
        {
            if ($type == 'thread' && !$onlyTitle) {
                return app(Threads::class);
            } elseif ($type == 'profile_post' && !$onlyTitle) {
                return app(ProfilePosts::class);
            } elseif (empty($type) && !$onlyTitle) {
                return app(AllPosts::class);
            } elseif ($onlyTitle) {
                return app(Thread::class);
            }
        }
    }
    
    AlgoliaSearchFactory创建的对象有一个方法search,该方法需要一个$searchQuery

    interface AlgoliaSearchInterface
    {
        public function search($searchQuery);
    }
    
    DatabaseSearchFactory创建的对象具有不需要任何参数的搜索方法

    interface DatabaseSearchInterface
    {
        public function search();
    }
    
    Search现在将SearchFactory生成的最终对象作为参数,它可以实现AlgoliaSearchInterfaceDatabaseSearchInterface,这就是为什么我没有输入提示

    getResults方法现在必须找出search变量的类型(它实现的接口),以便将$searchQuery作为参数传递或不传递

    这就是控制器如何使用搜索类来获得结果。 类搜索 { 受保护的美元战略

        public function __construct($search)
        {
            $this->strategy = $search;
        }
    
        public function getResults()
        {
            if(isset(request('q')))
            {
                $results = $this->strategy->search(request('q'));
            }
            else
            {
                $results = $this->strategy->search();
            }
        }
    }
    
    
    class SearchController(Search $search)
    {
        $results = $search->getResults();
    }
    

    根据所有@Transitive建议,这就是我想到的。我唯一无法解决的问题是如何在没有if语句的情况下调用getResults方法中的search

    我将此代码重构为:

    保留请求参数以统一接口中的搜索方法

    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);
        }
    }
    

    这样做的好处是,不要将请求包含在构造函数中,这一点非常重要。通过这种方式,您可以在应用程序生命周期中创建实例,而无需请求。这有利于缓存、可测试性和模块化。我也不喜欢应用程序和请求方法,因为它们凭空抽取变量,降低了可测试性和性能性能。

    你能分享更多详细信息吗?这看起来毕竟不是有效的PHP代码。另外,看看奇怪的。这篇文章的第一个版本没有包括任何函数部分-
    类搜索{
    后面紧接着是
    if
    语句我不清楚问题出在哪里;听起来您对代码有表面上的顾虑?实际上是的,我想避免所有这些if-else语句,并使代码更干净可能是因为我对问题的解释不清楚(我的意思是代码不清楚)。首先,onlyTitle不是由'type'决定的,而是由'only_title'参数决定的。因此,当您调用$request->get('type')时,将不会获得onlyTitle的值,因此将找不到该方法。此外,当给定类型时(例如,该类型='thread')。有两种不同的策略可以基于请求('q')搜索“线程”。如果请求('q')存在,则使用Algolia搜索“线程”,否则使用数据库搜索“线程”。因此,在您的回答中,如果($request->missing('q')){return$this->databaseSearch();},则有以下行($this->databaseSearch();)。当请求('q')),则我必须检查请求(“类型”)以及请求(“仅标题”)的值,以确定搜索策略是的,我将继续检查积极案例,处理它们并立即返回。这样,您只需
    interface DatabaseSearchInterface
    {
        public function search();
    }
    
        public function __construct($search)
        {
            $this->strategy = $search;
        }
    
        public function getResults()
        {
            if(isset(request('q')))
            {
                $results = $this->strategy->search(request('q'));
            }
            else
            {
                $results = $this->strategy->search();
            }
        }
    }
    
    
    class SearchController(Search $search)
    {
        $results = $search->getResults();
    }
    
    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);
        }
    }