PHP的多个elseif语句是否会影响性能?

3
我是您的助手,下面是您需要翻译的内容:

在过去的几周中,我正在编写一个PHP网站,一直有一个问题困扰着我。在我的index.php文件上,我将所有的模板文件路由到如下位置:

    if(isset($_GET['search'])){
        include_once 'template/template.search.php';
    }
    elseif(isset($_GET['newsletter'])){
        include_once 'template/template.newsletter.php';
    }
    elseif(isset($_GET['product'])){
        include_once 'template/template.product.php';
    }
    elseif(isset($_GET['categories'])){
        include_once 'template/template.categorie.php';
    }
    elseif(isset($_GET['about'])){
        include_once 'template/template.about.php';
    }
    elseif(isset($_GET['sitemap'])){
        include_once 'template/template.sitemap.php';
    }
    else
    {   
        include_once 'template/template.index.php';     
    }

但对我来说,这看起来不太干净。有没有更好的处理类似工作的可能性?

我已经尝试过这样做,但对我来说并没有起作用。

    $i = 0 ;
    switch($i){
    case(isset($_GET['search'])):
        include_once 'template/template.search.php';
        break;
    default:
        include_once 'template/template.index.php'; 
        break;
}

编辑:标题中的更好的写作可能会误导一些人,所以我肯定在寻找最佳性能。

注:本文主要讨论IT技术相关内容。


2
switch语句可以解决这个问题。 - Ryan
1
你可以使用 switch。http://ca2.php.net/manual/zh/control-structures.switch.php - dnagirl
2
另一个选择可能是使用类似于.htaccess的路由。 - ficuscr
1
@ithcy,你正在用自己的答案或建议轰炸这个页面,却没有提供任何自己的解决方案或建议。你是在恶意提问以贬低那些试图帮助别人的人,还是真的打算为问题提供一些有建设性的东西(比如实际的答案)?你似乎知道最好的解决方案,但选择不做出贡献。 - jnthnjns
1
@ithcy 我同意我的评论很荒谬,没有好好想过就匆忙发表了。一旦意识到这一点,我就停下来并投票支持我认为最好的答案。我没有垃圾邮件所有其他的评论/答案。我只是厌倦了普遍的开发态度,“我最棒了,我拒绝帮助这样琐碎的问题,但我肯定会花时间告诉你我做得有多糟糕。” - jnthnjns
显示剩余9条评论
6个回答

11

这个怎么样?

$templates = array('search',
                   'newsletter',
                   'product',
                   'categories',
                   'about',
                   'sitemap',
                   'index');

foreach ($templates as $template)
{
    if (isset($_GET[$template]))
    {
        include_once "template/template.$template.php";
        break;
    }
}

你真的应该指定一个有效模板的数组,这样更安全。

我猜另一种方法是反过来搜索:

$templates = array('search',
                   'newsletter',
                   'product',
                   'categories',
                   'about',
                   'sitemap',
                   'index');

foreach ($_GET as $key => $val)
{
    if (in_array($key, $templates))
    {
        include_once "template/template.$key.php";
        break;
    }
}

1
include_once 后面可能需要加上一个 break - user645280
@alfasin - 实际上我在写我的回答时没有看到你的回答,但是我认为你值得得到一个+1,所以我给你点了赞。 - Andrew Cheong

4
假设$_GET只包含includes,你可以这样做:
foreach ($_GET as $key => $val){
    if(isset($key)){
        include_once 'template/template.'.$val.'.php';
        break;
    }
}

@RPM,我不明白你的问题:$_GET确实是一个数组。 - Nir Alfasi
此外,他的值并不总是在文件名中。请参见“类别”作为示例。 - phpisuber01
@itchy,我不理解你的问题,你的意思是$_GET ['search']会被设置,但我们不应该包含' template / template.search.php '吗? - Nir Alfasi
这个会起作用,但如果查询是 ?newletter=newletter&foo=1,它会尝试包含不存在的 template/template1.php - Adam Elsodaney
不,我的意思是如果$_GET['search']$_GET['newsletter']都存在(如果URL是?search=1&newsletter=1),那么你的代码将包括template/template.search.phptemplate/template.newsletter.php两个模板。 - glomad
显示剩余10条评论

3

虽然并没有非常清晰,但switch语句是最好的选择。可读性提高了150倍。

switch(true) {
    case isset($_GET['search']):
        include_once 'template/template.search.php';
        break;

    // do more

    default:
        include_once 'template/template.index.php';
        break;
}

我不同意。在这种特定情况下,使用switch语句会降低可读性。 - glomad
2
我同意itchy的观点,如果我是OP,我会选择接受@acheong87的答案! - Nir Alfasi
2
这里的大多数答案都是合理的,但我认为在这种方式中使用循环假定get变量的键将与文件名的一部分完全匹配。由于我们在SO上尽量不本地化答案,因此我选择了一个形式,以满足其他好奇用户的需求。 - phpisuber01
@phpisuber01 我会放弃使用 switch,并且在页面选择器和实际页面名称之间强制保持一致性,特别是考虑到一个好奇的初学者漫游在这个页面上。在我看来,代码可读性和最小数据冗余是两个你不能太早学习的原则。 - kuroi neko

2

只是一些随意的想法...

  • 性能不是问题。
    即使一系列的if没有else,也能在几微秒内执行完。

但代码可维护性和稳健性确实是问题。

我发现使用switch略带hackish有些不令人满意甚至有危险,因为:

  • 重要信息(GET索引和实际页面名称)仍然重复并埋在大量重复的代码中。
  • 如果两个条件同时满足,则switch会表现得奇怪(我想它会选择第一个满足的条件,但这仍然不太干净)。
  • 添加或删除页面仍需要复制/删除3或4行代码,并且无意中复制一个块可能会被忽视并将程序员置于“我确定这件事已经解决了(但实际上没有)”的烦恼情境中。

实际上,我觉得界面有点奇怪。传递一个单一的“目标”变量,该变量枚举可能的页面,对我来说更一致。这将消除两个页面选择标志同时设置的奇怪情况。

然后你可以有一个简单的目标列表,计算目标页面的名称,或者将它们存储在关联数组中(如果你真的无法以一致的方式命名它们,尽管我想知道什么奇怪的要求会阻止你这样做)。

我考虑稳健性的关键点是

  • 没有数据重复
  • 没有“懒惰”的默认情况(除非默认值来自于功能要求)

基于所有这些原因,我会改变选择页面的方式:

$pages = array (                  // single data source
    "search",
    "newsletter",
    // etc...
    );
@$page = $pages=[$_GET["page"]];  // single page selector
if (!$page) $page = "index";      // explicit default case

include "template/template.$page.php"; // no reason to include only once

// if someone else happens to include the template, better have the page
// break down immediately and correct the problem than letting a piece of
// buggy code live happily somewhere in your scripts

0
你可以使用数组:如果找到键,则使用它,否则只需使用默认值:
<?php
$tpl = array(
'search' => 'template/template.search.php',
'newsletter' => 'template/template.newsletter.php',
'product' => 'template/template.product.php'
#...
);

foreach($_GET as $get){
   if(array_key_exists($get, $tpl)) include_once($tpl[$get]); // assuming search is within $get
}

?>

0
你可以在查询字符串中使用变量(如t)来指示要使用的模板,然后根据此动态地包含模板名称。因此,如果您的URL类似于:mysite.com/page.php?t=newsletter&blah=1&...,那么您只需要执行以下操作:
include_once('template/template.' . $_GET['t'] . '.php');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接