如何使用PHP switch语句检查字符串是否包含一个单词(但也可以包含其他单词)?

37

我正在使用PHP的switch语句,根据页面URL参数中传递的关键词包含特定文件。

例如,URL可能是:...page.php?kw=citroen%20berlingo%20keywords

在页面内,我想使用类似于这样的代码:

<?
    switch($_GET['kw']){

        case "berlingo":     
            include 'berlingo.php'
            break;
        case "c4":
            include 'c4.php';
            break;

    } 
?>
在第一种情况下,我想要包含berlingo.php文件,如果关键字参数包含berlingo,但它不一定是那个关键字短语。

例如,如果关键字是berlingo,但citroen berlingo,我想要包含berlingo.php文件。

如何使用PHP case select(switch语句)评估给定字符串是否包含一个值?

谢谢。
8个回答

49
根据这个问题这个答案,我研究出了以下解决方案(仍然使用case选择)。

您可以使用stristr()strstr()。 我选择在这种情况下使用 stristr()的原因是因为它是不区分大小写的,因此更加健壮。

例子:

$linkKW = $_GET['kw'];

switch (true){
   case stristr($linkKW,'berlingo'):
      include 'berlingo.php';
      break;
   case stristr($linkKW,'c4'):
      include 'c4.php';
      break;
}

如果您愿意,也可以使用stripos()strpos(),这是(感谢Fractaliste,但我个人认为这种方法更难阅读。与上面另一种方法类似;我选择了不区分大小写的方式。

示例:

$linkKW = $_GET['kw'];

switch (true){
   case stripos($linkKW,'berlingo') !== false:
      include 'berlingo.php';
      break;
   case stripos($linkKW,'c4') !== false:
      include 'c4.php';
      break;
}

4
使用strpos()函数的您的想法是: switch (true) {case strpos($name, 'incident') !== false: /* 任务 */ - Fractaliste

8

由于在switch语句中只进行简单的相等性测试,因此它在这里并没有什么帮助。您需要通过一个字符串匹配函数来运行该字符串,最适合的是strpos。直截了当的答案是:

if (strpos($_GET['kw'], 'berlingo') !== false) {
    include 'berlingo.php';
} else if (strpos($_GET['kw'], 'c4') !== false) {
    include 'c4.php';
} … and so on …

更加优雅的解决方案可能是这样的:
$map = array('berlingo' => 'berlingo.php', 'c4' => 'c4.php', …);
foreach ($map as $keyword => $file) {
    if (strpos($_GET['kw'], $keyword) !== false) {
        include $file;
        break;
    }
}

或者,如果关键字和文件之间的对应关系总是1:1:

$keywords = array('berlingo', 'c4', …);
foreach ($keywords as $keyword) {
    if (strpos($_GET['kw'], $keyword) !== false) {
        include "$keyword.php";
        break;
    }
}

1
您可以在 switch -> case 中使用正则表达式:
<?php

    $kw = filter_input(INPUT_GET, "kw");

    switch($kw){

        case (preg_match('/*berlingo*/', $kw) ? true : false):     
            include 'berlingo.php';
            break;

        case "c4":
            include 'c4.php';
            break;

    } 
?>

1

您可以使用 strpos函数,如下:

if(strpos($_GET['kw'],'berlingo') !== false) {
 include 'berlingo.php';
}
if(strpos($_GET['kw'],'c4') !== false) {
 include 'c4.php';
}

1
$keywords = array('berlingo', 'c4');
foreach($keywords as $keyword)
  if(strpos($_GET['kw'], $keyword) !== FALSE)
    include("$keyword.php");

虽然这样做很方便,但我不建议根据用户输入包含php文件。


3
如果像这种情况一样,通过白名单进行匹配,那么根据用户输入包含文件就不会有问题。 - deceze

1
在我看来,如果您通过GET变量包含脚本,则会出现“代码异味”,但是您可以使用带有方法的值类来优雅地执行此操作,这些方法的逻辑返回值对象本身(如果为真)。
关键是要记住,switch语句将执行任何其中$switch == $case的代码(松散匹配)。因此,只需创建返回$this或什么也不返回的方法即可。
例如:
class Haystack {
    public $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function contains($needle):
    {
        if (strpos($this->value, $needle) !== false)
            return $this;
    }
}

$kw = new Haystack($_GET['kw']);

switch ($kw) {
    case $kw->contains('berlingo'):
        require_once 'berlingo.php';
    case $kw->contains('c4'):
        require_once 'c4.php';
}

当然,您可以慷慨地使用类型提示来装饰此代码。如果您这样做,并且未使用支持可空返回类型的PHP版本(即public function contains(string $substring): ?Haystack方法签名),那么您的类将不得不详细说明。
示例:
final class Haystack {
    private $value;
    private $isMain;

    public function __construct(string $value, bool $isMain = true)
    {
        $this->value = $value;
        $this->isMain = $isMain;
    }

    final public function contains($needle): Haystack
    {
        if (strpos($this->value, $needle) !== false)
            return $this;
        return new Haystack($needle, false);
    }
}

这样,如果您的显式匹配逻辑在方法内失败,如果由于某种原因new Haystack($_GET['kw']) == new Haystack($needle);为真,则不匹配的属性"$isMain"将确保它们不被评估为相等。
再次强调,我建议您重新审视为什么要在这种特定情况下这样做; 传统上,Composer是一种依赖管理工具,可通过PSR自动加载标准包含需要的各种脚本。与路由器库结合使用可能是解决实际需求最有用的方式。

0

我知道这已经晚了很多,但是作为旁注,如果期望一对一的关系,可以完全避免循环。

大致上可以这样做:

$map = array('berlingo' => 'berlingo.php', 'c4' => 'c4.php', …);

if( !isset( $map[$_GET['kw']] ))
    throw new Exception("Blah!!");

include $map[$_GET['kw']];

...只是分享给新手们的一些FYI。


0

strpos() 是用于检查字符串是否包含另一个字符串的函数。

还有其他函数可用于检查字符串的相似性等。

switch 不适用,因为它将静态表达式与单个值进行比较。您需要使用if语句。


Core Xii,您能否提供我所使用的开关的正确版本,以便我可以实现想要完成的任务?我尝试使用strpos()重写开关,但出现了错误,我猜我不知道该怎么做。 - sebastian

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