可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using a PHP switch to include certain files based on the incoming keywords passed in a parameter of the page's URL.
The URL, for example, could be: ...page.php?kw=citroen%20berlingo%20keywords
Inside the page, I'd like to use something like this:
<?
switch($_GET['kw']){
case "berlingo":
include 'berlingo.php'
break;
case "c4":
include 'c4.php';
break;
}
?>
What I want to do in the first case is include the berlingo.php
file if the keyword parameter contains berlingo
, but it doesn't have to be exactly that keyword alone.
For example, I want to include the berlingo.php
file if the keyword is berlingo
, but also if it's citroen berlingo
.
How can I evaluate if a given string contains a value using a PHP case select (switch statement)?
Thanks.
回答1:
Based on this question and this answer, the solutions I've come up with (while still using a case select) are below.
You can use either stristr() or strstr(). The reason I chose to use stristr()
in this case is simply because it's case-insensitive, and thus, is more robust.
Example:
$linkKW = $_GET['kw'];
switch (true){
case stristr($linkKW,'berlingo'):
include 'berlingo.php';
break;
case stristr($linkKW,'c4'):
include 'c4.php';
break;
}
You could also use stripos() or strpos() if you'd like (thanks, Fractaliste), though I personally find this more difficult to read. Same deal as the other method above; I went the case-insensitive route.
Example:
$linkKW = $_GET['kw'];
switch (true){
case stripos($linkKW,'berlingo') !== false:
include 'berlingo.php';
break;
case stripos($linkKW,'c4') !== false:
include 'c4.php';
break;
}
回答2:
Since in a switch
statement only a simple equality testing will be performed it won't help you much here. You need to run the string through a string matching function, best suited of which is strpos
. The straight forward answer is:
if (strpos($_GET['kw'], 'berlingo') !== false) {
include 'berlingo.php';
} else if (strpos($_GET['kw'], 'c4') !== false) {
include 'c4.php';
} … and so on …
The more elegant solution would be something like this:
$map = array('berlingo' => 'berlingo.php', 'c4' => 'c4.php', …);
foreach ($map as $keyword => $file) {
if (strpos($_GET['kw'], $keyword) !== false) {
include $file;
break;
}
}
Or, if the correspondence between the keyword and the file is always 1:1:
$keywords = array('berlingo', 'c4', …);
foreach ($keywords as $keyword) {
if (strpos($_GET['kw'], $keyword) !== false) {
include "$keyword.php";
break;
}
}
回答3:
You can use strpos function as:
if(strpos($_GET['kw'],'berlingo') !== false) {
include 'berlingo.php';
}
if(strpos($_GET['kw'],'c4') !== false) {
include 'c4.php';
}
回答4:
$keywords = array('berlingo', 'c4');
foreach($keywords as $keyword)
if(strpos($_GET['kw'], $keyword) !== FALSE)
include("$keyword.php");
I wouldn't recommend including php files based on user input though.
回答5:
You can also use regular expression in 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;
}
?>
回答6:
strpos()
is one for checking if a string contains another string.
There are other functions for checking similarity of strings, etc.
A switch
won't do, though, since it compares static expressions against a single value. You'll have to use if
s.
回答7:
I know this is WAY after the fact, but just as an aside, one can always avoid the loop altogether if expecting a 1:1 relationship.
Something along the lines of:
$map = array('berlingo' => 'berlingo.php', 'c4' => 'c4.php', …);
if( !isset( $map[$_GET['kw']] ))
throw new Exception("Blah!!");
include $map[$_GET['kw']];
...just sharing as an FYI for newbies.
回答8:
In my opinion, it's a code smell if you're including scripts via GET variables, but you can do this elegantly using a value class with methods whose logic return the value object itself if true.
The idea is to keep in mind that a switch
statement will execute any code where $switch == $case (a loose match). So just create methods which either return $this
, or nothing at all.
Example:
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';
}
You can, of course, generously garnish this code with typehints. If you do, and are not using a version of PHP which supports nullable return types (ie a method signature of public function contains(string $substring): ?Haystack
) then your class would have to elaborate to reflect that.
Example:
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);
}
}
This way, if your explicit matching logic fails inside the method, if for some reason new Haystack($_GET['kw']) == new Haystack($needle);
is true, the non-matching property "$isMain" will ensure they are not evaluated as equal.
Again, I would re-examine why you'd want to do this in the first place for this particular situation; traditionally, Composer is a dependency management tool which would be used to include various scripts you need via a PSR autoload standard. That in combination with a Router library would probably be the most useful to address your actual needs.