0

我正在努力使用一个简单的函数来循环遍历数组并true仅在它在数组元素之一中找到给定子字符串时才返回。

出于某种原因,我总是得到false......即使$email参数包含有效域之一。例如:scoobydoo@domain1.com

function check_email($email) {
    $whitelist_domains = array(
        '@domain1.com',
        '@domain2.com',
        '@domain3.com'
    );
    $output = FALSE;
    foreach ($whitelist_domains as $domain) {   
        $pos = strpos( $email, $domain ); 
        if ( $pos ) {
            $output = TRUE;
        }
    }
    return $output;
}
4

6 回答 6

2

如果您找到域,则不会破坏循环,因此您得到的实际上是仅检查 LAST 字符串的结果。break;之后添加$output = TRUE;

于 2012-03-15T21:52:50.423 回答
1

来自strpos的官方文档:

警告

此函数可能返回布尔值 FALSE,但也可能返回计算结果为 FALSE 的非布尔值。请阅读有关布尔值的部分以获取更多信息。使用 === 运算符测试此函数的返回值。

并确保在设置$output为 true 后添加中断。

于 2012-03-15T21:54:19.380 回答
0

这是一个使用运算符的好功能===,因为它确保值和类型相等 ( 1==true, 但是1!==true)

if (strpos( $email, $domain )!==false) {
    $output = TRUE;
}
于 2012-03-15T21:55:24.043 回答
0

改变

if ( $pos ) {

if ( $pos !== false) {

这是因为 strpos 返回 0,这将等同于 false,即使找到了字符串。

于 2012-03-15T21:55:45.920 回答
0

您应该在此更改您的代码:

function check_email($email) {
    $whitelist_domains = array(
        '@domain1.com',
        '@domain2.com',
        '@domain3.com'
    );

    foreach ($whitelist_domains as $domain) {   
        if ( strpos( $email, $domain ) !== false ) {
            return true;
        }
    }
    return false;
}

的文件strpos

引用手册(http://php.net/manual/en/function.strpos.php):

!== 运算符也可以使用。使用 != 不会按预期工作,因为 'a' 的位置为 0。语句 (0 != false) 的计算结果为 false。

示例代码

<?php
$mystring = 'abc';
$findme   = 'a';
$pos = strpos($mystring, $findme);

// The !== operator can also be used.  Using != would not work as expected
// because the position of 'a' is 0. The statement (0 != false) evaluates 
// to false.
if ($pos !== false) {
     echo "The string '$findme' was found in the string '$mystring'";
         echo " and exists at position $pos";
} else {
     echo "The string '$findme' was not found in the string '$mystring'";
}
?>
于 2017-09-03T05:45:27.653 回答
0

以下是两种具有不同优点的直接/常用方法:

方法#1:非正则表达式方法

function check_email1($email){
    $whitelist_domains=['@domain1.com','@domain2.com','@domain3.com'];
    foreach($whitelist_domains as $domain){
        if(strpos($email,$domain)!==false){
            return true;  // allow quick return (exit loop & function asap)
        }
    }
    return false;  // default response
}

方法#2:正则表达式方法

function check_email2($email){
    $whitelist_pattern='/@(?:domain1\.com|domain2\.com|domain3\.com)$/';  // condense if possible /@domain[123]\.com$/
    return (bool)preg_match($whitelist_pattern,$email);  // convert 0 or 1 output to boolean (false/true)
}

演示链接

输入/函数调用

$emails=['user@domain1.com','bad@bad.com'];
foreach($emails as $email){
    echo "$email\n";
    var_export(check_email1($email));
    echo "\n";
    var_export(check_email2($email));
    echo "\n\n";
}

输出

user@domain1.com
true
true

bad@bad.com
false
false

优点/缺点

  • strpos()在大多数情况下会胜过正则表达式函数。您的默认方法应该是使用字符串函数,并且仅在字符串函数效率较低或编码过于复杂时才更改为正则表达式。相关页面:PHP 字符串函数还是 PHP 中的正则表达式哪个更高效?

  • 与#2 相比,#1 中的循环使得代码块看起来更笨重(如果您将模式直接写入preg_match()$whitelist_domains,则可以将其压缩为单行)。

  • 处理strpos(). 这些错误可能包括:

    • false不检查if条件
    • 以错误的顺序书写haystackandneedle
  • #2 确实需要一些关于正则表达式(转义、字符类、替代项等)的知识,这对于没有经验的编码人员来说可能是一种威慑。根据您编写正则表达式模式的方式以及将有多少域列入白名单,#2 可能比 #1 更难维护。

  • #2 的额外好处是能够domain.com通过元字符检查子字符串是否出现在单词的末尾$。因此,正则表达式提供了更强的验证。

于 2017-09-03T03:42:13.717 回答