使 PHP glob 搜索顺序不敏感

Make PHP glob search order insensitive

我正在自学 php 如果这是一个愚蠢的问题,我很抱歉。我有一个包含许多文件夹的文件夹,所有文件夹都包含 JPG 文件。我正在使用下面的代码搜索名称(and/or 文件夹名称)包含用户发送的所有关键字的文件(示例中限制为 4 个关键字)。如果关键字的发送顺序与它们在 folder/file 字符串中出现的顺序相同,但不会返回具有不同顺序的相同单词的字符串,则此方法可以正常工作。我怎样才能做到这一点?非常感谢!

<?php

$keywords = $_REQUEST['keywords'];

$exploded_keywords = explode(" ", $keywords );

if (isset($exploded_keywords[4])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'.$exploded_keywords[3].'*'.$exploded_keywords[4].'*'; } else { 

if (isset($exploded_keywords[3])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'.$exploded_keywords[3].'*'; } else { 

if (isset($exploded_keywords[2])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'.$exploded_keywords[2].'*'; } else { 

if (isset($exploded_keywords[1])) { $inclusion = '*'.$exploded_keywords[0].'*'.$exploded_keywords[1].'*'; } else { 

if (isset($exploded_keywords[0])) { $inclusion = '*'.$exploded_keywords[0].'*'; }}}}}

$files = glob("$inclusion/*.[jJ][pP][gG]", GLOB_BRACE);

$num = $files[0];

for ($i=0; $i<count($files); $i++) { 
   $num = $files[$i]; 
   $err = 0;
   foreach($exclude as $term) {
      if (stristr($num,$term)) { 
         $err++; }}
   if( !$err > 0 ) { // display thumbnails... }} ?>

我会使用正则表达式来实现这一点。请参阅最后一段代码,了解更少的自我解释但直接的版本。

<?php
//Its bad practice to use $_REQUEST, you should use $_GET or $_POST if you can..
$keywords = $_REQUEST['keywords'];

//Let's prepare our regex to match our keywords.   
$exploded_keywords = explode(" ", $keywords );
$regex = "/";

//Loop trough your keywords and add them to the regex.
// ?= is a lookahead, if you want to know what it does. http://www.rexegg.com/regex-lookarounds.html
//preg_quote() will escape your keywords so they don't break your regex. Caracters such as ( ) . ? * etc.
foreach($exploded_keywords as $keyword){
    $regex .= "(?=.*".preg_quote($keyword, '/').")";
}

/* 
 * The following block of code has been added just in case it's useful to someone.
 * This will return a match if ANY one keyword is found within the file name. (Case insensitive)
 *
 * $regex = "/.*(";
 * $tmp = '';
 * foreach($exploded_keywords as $keyword) {
 *  $tmp = $tmp."|".preg_quote($keyword, '/');
 * }
 * $regex .= ltrim($tmp, '|') . ").*\.jpg/i";
 */
//match a jpg file. This version is case insensitive for the keywords and the extension.
$regex .=".*\.jpg/i";
//This would make it case sensitive but for the extension
//$regex .=".*\.[jJ][pP][gG]/";

//Now let's get the files
$files = glob("*.[jJ][pP][gG]", GLOB_BRACE);

//Let's get our matches
//preg_grep will look in your array values for matches and return the entries as a array. 
//array_values will reindex the keys of the returned array. Otherwise they keep their original keys. 
$matches = array_values(preg_grep($regex, $files));
//Verify your results
print_r($matches);

简化版:

<?php
$keywords = preg_quote($_REQUEST['keywords']);
$regex = (!empty($keywords)) ? "/(?=.*". str_replace(' ', ')(?=.*', $keywords).")"  . ".*\.[jJ][pP][gG]/" : '/.*/';
$files = glob("*.[jJ][pP][gG]", GLOB_BRACE);
$matches = array_values(preg_grep($regex, $files));
print_r($matches);

编辑:在生成正则表达式时添加了 preg_quote(),因为关键字显然来自用户输入。