0

我有一个 PHP 脚本,其中包含特殊引用者的不同页面:

$ref_found = false; 

// get referer if exists 
$referer = false; 
if ( isset($_SERVER['HTTP_REFERER']) ) { 
    $referer = $_SERVER['HTTP_REFERER']; 
    // get content of list.txt 
    $list = explode(chr(10), file_get_contents('list.txt')); 
    foreach ( $list as $l ) { 
        if ( strlen($l) > 0 ) { 
            if ( strpos( $referer, $l ) ) { 
                $ref_found = true; 
            } 
        } 
    } 
} 

// include the correct file 
if ( $ref_found ) { 
    require_once('special_page.html'); 
} else { 
    require_once('regular_page.html'); 
} 

引用数据库位于简单的 txt 文件 (list.txt) 中,如下所示:

domain1.com

domain2.com

domain3.com

不幸的是,此脚本仅适用于列表中的最后一个域 (domain3.com)。

我应该添加什么?\n?
或者以不同的方式创建域数据库更好?

4

2 回答 2

2

问题是,当explode()您列出域名列表时,每个项目周围都会出现空格。至少,您将在\n某处有一个换行符 ( ),因为文件中的换行符可能是\r\n.

所以你正在检查类似" domain1.com"或可能"\ndomain1.com",或可能的东西"domain1.com\n"。由于引荐来源标头中不存在这个额外的空格,因此它与您期望的不匹配。

通过调用trim()您找到的每个值,您将获得一个干净的域名,您可以使用它来进行更有用的比较:

$list = explode("\n", file_get_contents('list.txt'));
foreach ($list as $l) {
    $l =  trim($l);
    if ((strlen($l) > 0) && (strpos($referer, $l) !== false)) {
        $ref_found = true;
        break;
    }
}

我还对您的代码进行了其他一些小的更新:

  1. 我不再使用chr(),而是使用了字符串文字 ( "\n")。只要您使用双引号,它将是文字换行符,而不是实际的\and n,并且对于阅读您的代码的人来说,字符串文字更容易理解。

  2. 我从一个"\r"角色(第 10 章)切换到了一个"\n"角色(第 13 章)。有几种不同的换行格式,但最常见的是"\n""\r\n"。通过 exploding on "\n",您的代码将适用于两种格式,其中"\r"仅适用于第二种格式。

  3. 我结合了你的两个if陈述。这是一个非常小的更新,除了(在我看来)使代码更易于阅读之外没有太大影响。

  4. 我更新了你strpos()对 false ( !==) 的字面比较。这段代码可能不是问题,因为referrer 值将以 开头http://,但这是一个好习惯。如果子字符串恰好出现在父字符串的开头,strpos()将 return 0,这将在您的原始代码中被解释为 false。

  5. break如果您找到匹配的域名,我会在您的循环中添加一条语句。一旦找到并设置标志,就没有理由继续检查列表中的其余域,并break允许您取消foreach循环的其余部分。

于 2013-07-03T06:15:05.617 回答
0
chr(13) == "\n"
chr(10) == "\r"

"\n"很可能是你想要的。

于 2013-07-03T05:53:40.490 回答