【问题标题】:Optimize this PHP Code?优化这个 PHP 代码?
【发布时间】:2011-11-10 06:07:20
【问题描述】:

我目前正在开发一个包含许多数据馈送的混搭。为了在一页上显示用户想要的所有提要,我目前正在使用 if 语句与 MySQL 数据库进行交叉检查,如下所示:

if($var["type"]=="weather") 

$var 是调用 mysqli_fetch_array 的结果

然后包括与下面的功能(例如天气)相关的代码,然后是另一个提要的另一个“if”语句,依此类推。问题是会有很多提要,并且拥有所有这些“if”语句会很慢而且是多余的。

有什么办法可以优化这段 PHP 代码吗?

【问题讨论】:

  • 你怎么知道用户想要哪个types?如果是weather, sports, news,只需将其作为数据库查询本身的一部分。

标签: php mysql performance if-statement mysqli


【解决方案1】:

使用If 语句或Switch 语句将比您关心的更快。它可能看起来很难看且维护起来很麻烦,但它很快。

【讨论】:

    【解决方案2】:

    试试这个:

    $methods = array(
        "weather" => function() {
            // code
        },
    
        "otheroption" => function() {
        }
    );
    

    只需使用 then $var["type"] 作为数组中的索引即可获取函数:

    $methods[$var["type"]]();
    

    为了更好的可读性,您显然可以做类似的事情:

    $methods = array(
        "weather" => "wheater_function",
    
        "otheroption" => "other_function"
    );
    

    然后以这种方式调用函数:

    call_user_func($methods[$var["type"]]);
    

    为了更加面向对象,我们显然可以将实现特定接口的对象存储在数组中,或者存储对象重新定义 __call() 魔术方法并像函数一样使用它。

    【讨论】:

    • 虽然这可行,但它是一个简单问题的相当混乱的解决方案
    • 这是最优雅的,如果我理解会有很多不同的类型;它肯定是最具扩展性的解决方案
    • 当然切换是最好的吗?声明匿名函数不会增加不必要的开销吗?
    • 我对此表示赞同,因为它在技术上是有效的,不值得否定,而不是因为它是这里的最佳答案。
    • 嗯...它确实有点像策略模式,但所有代码仍然紧密耦合在一个 $methods 数组中。策略更多的是关于将实现特定算法的代码位重构为单独的代码模块(通常是类),然后可以通过工厂/工厂方法按需实例化。
    【解决方案3】:

    用于救援的多态性。

    inteface FeedInterface {
      public function retrieve($params);
    }
    
    class FeedWeather implements FeedInterface {
    
      public function retrieve($params) {
        //retrieve logic for weather feed
      }
    
    }
    
    class FeedSports implements FeedInterface {
    
      public function retrieve($params) {
        //retrieve logic for sports feed
      }
    
    }
    

    通过使用 PHP 类自动加载,上述每个声明都可以在一个单独的文件中,也可能是命名空间。那么您的提要检索代码可能如下所示:

    $class = 'Feed'.$var["type"];
    $feed = new $class;
    
    $feed->retrieve($params);
    

    这过于简化了,需要一些额外的代码来处理错误,发现不存在的类等等,但这个想法应该很清楚。

    【讨论】:

    • 如果我们想改变类怎么办?也许我们只想为单元测试更改类...我们可以这样做吗?
    • 我不明白为什么不这样做。该类的唯一要求是实现 FeedInterface。实例化代码需要进行一些更改以促进单元测试,但就像我说的那样,这里的示例已简化,在实际应用中需要更多管道。
    • 问题是你通过反射引用类的方式!
    • $class= '饲料'.$var["type"];
    • 好的。从广义上讲,它是反射。现在,为什么它实际上很糟糕?
    【解决方案4】:

    创建一个将函数与每种提要类型相关联的数组:

    $actions = array("weather" => "getWeather",
                     "news"    => "getNews");
    

    然后用call_user_func调用正确的:

    call_user_func($actions[$var["type"]]);
    

    【讨论】:

      【解决方案5】:

      另一种解决方案可能是使用关联数组将“类型”映射到自定义函数。

      例如(伪代码)

      function handle_wheater_logic() {
         // ... your code goes here
      }
      
      function handle_news_logic() {
        // .. your code goes here
      }
      
      
      $customFunctions = array("wheater" => "handle_wheater_logic", "news" => "handle_news_logic");
      
      while ($row = mysql_fetch_...) {
          call_user_func ($customFunctions[$row["type"]])
      }
      

      这将消除使用大量 if 语句的需要。您也可以在配置文件中进行“类型到函数”的映射,或者只存储自定义函数的名称以在数据库表中为每个“类型”调用 - 这取决于您。

      您当然也可以将参数传递给自定义函数。只需查看 call_user_func[_array] 的文档即可。

      【讨论】:

        【解决方案6】:

        消除大量 if 语句和仅检查一个条件的巨大 switch 语句的一个很好的解决方案是实现一种设计模式,例如策略模式。

        这样您就可以将每种类型的代码分开,从而更易于概览和管理。

        这是一个实现示例http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx

        即使您不会严格执行此操作,它也会为您提供一些关于如何优雅地解决此问题的想法。

        【讨论】:

          【解决方案7】:

          您可以使用switch 语句。

          【讨论】:

            猜你喜欢
            • 2010-12-14
            • 1970-01-01
            • 1970-01-01
            • 2017-07-13
            • 1970-01-01
            • 2019-11-05
            • 1970-01-01
            • 1970-01-01
            • 2012-03-13
            相关资源
            最近更新 更多