【问题标题】:How to return a boolean if a string contains one of an array of substrings?如果字符串包含子字符串数组之一,如何返回布尔值?
【发布时间】:2012-03-15 21:50:31
【问题描述】:

我正在努力使用一个简单的函数,该函数循环遍历一个数组并仅当它在数组的一个元素中找到给定的子字符串时才返回 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;
}

【问题讨论】:

  • strpos 可能返回 0,即 == false;使用 if($pos !== false) 代替
  • 您需要对$pos 进行严格比较,因为如果它在字符串的开头找到它,您的测试将失败,因为$pos = 0。改为if($pos === false)

标签: php if-statement foreach boolean strpos


【解决方案1】:

如果您找到域,您并没有打破循环,因此您得到的实际上是仅检查 LAST 字符串的结果。 只需在$output = TRUE; 之后添加break;

【讨论】:

  • 顺便说一句,有更有效的方法可以做到这一点,请查看 preg_match。你可以在没有循环的情况下做到这一点。
  • 轰隆隆!就是这样。当我第一次编写函数时,我在循环中使用了return TRUE(我认为return 会转义循环,对吧?)。我打算做 preg_match,但正则表达式语法总是让我有点头疼。对于一个短数组,它对性能有很大影响吗?
  • 我通常不喜欢这类东西,但我根据你的建议做了一些研究(使用 preg_match),我很惊讶地发现这篇文章......lzone.de/articles/php-string-search.htm。 ..声称 strpos() 实际上比 preg_match() 快。
  • 这取决于用例。 strpos 更快,但 PHP 循环很慢。写一个比较基准,如果你这样做了,就发布结果!
  • 我对你的想法很感兴趣,但我不清楚如何避免循环。您是否建议有一种方法可以 preg_match 整个数组?
【解决方案2】:

来自strpos的官方文档:

警告

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

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

【讨论】:

    【解决方案3】:

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

    if (strpos( $email, $domain )!==false) {
        $output = TRUE;
    }
    

    【讨论】:

    • 如果 strpos 返回 7,那么 (strpos === true) 是否为真?
    【解决方案4】:

    改变

    if ( $pos ) {
    

    if ( $pos !== false) {
    

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

    【讨论】:

      【解决方案5】:

      这里有两种直接/常用的方法,各有不同的优点:

      方法#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)
      }
      

      Demo Link

      输入/函数调用

      $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() 在大多数情况下会胜过正则表达式函数。您的默认方法应该是使用字符串函数,并且仅在字符串函数效率较低或编码过于复杂时才更改为正则表达式。相关页面:Which is more efficient, PHP string functions or regex in PHP?

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

      • 处理strpos() 时有时会出现简单/常见错误。这些错误可能包括:

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

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

      【讨论】:

        【解决方案6】:

        你应该改变你的代码:

        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) 评估 为假。

        示例代码

        <?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'";
        }
        ?>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-23
          • 2014-10-30
          • 2014-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多