在HTML搜索表单的1个输入文本中搜索多个值

时间:2016-12-30 07:05:19

标签: php mysql sql mysqli

我有一个使用HTML的常用搜索表单,它将从mysql中提取数据(连接使用PHP和mysqli)。该函数在搜索1值时效果很好,但我想让用户可以搜索多个用逗号(,)分隔的值。

例如: Searching 1 value works well 搜索1值效果很好。

但我想在搜索框中搜索2个或更多值,例如: 42-7278954,53-1217544,07-2517487,...

我希望用户可以输入如下图所示的内容,结果将有2行 - > CN_no 42-7278954 53-1217544

enter image description here

我到目前为止的查询是:

$sql = "SELECT * FROM mock_data WHERE CN_no IN ('{$CN_no}') OR doc_no IN ('{$doc_no}')";

注意:CN_no是"货件代码"和doc_no是"参考号"

但是好吧......由于语法不正确,显然会给我一个错误。

请帮我修改一下。谢谢。

========根据vp_arth的回答更新查询========

$cn = explode(',', $CN_no);
$incn = str_repeat('?, ', count($cn)-1).'?';
$doc = explode(',', $doc_no);
$indoc = str_repeat('?, ', count($doc)-1).'?';

$query = "SELECT * FROM mock_data WHERE CN_no IN ({$incn}) or doc_no IN ({$indoc})";
$result = $conn->query($query , array_merge($incn, $indoc));

但它给了我一个error

9 个答案:

答案 0 :(得分:2)

这是在prepared statements中使用mysqli和动态输入的可能解决方案。 parameter binding的输入是静态的,在这种情况下参数是strings

/**
 * connecting to the database
 * defining in how manye columns you want to search (important to create the correct amount of arguments)
 */
$conn = new mysqli('localhost', 'root', '', 'test');
$columnsToSearch = 2;

/**
 * the numbers you want to search delimited by ","
 */
$CN_no = '42-7278954,53-1217544,07-2517487';
$cn = explode(',', $CN_no);

/**
 * writing the numbers to search into variables
 * putting the references of those variables into an array
 * 
 * the references will be used as arguments for the prepared statement
 */
$values = array();
for ($i = 0; $i < $columnsToSearch; $i++) {
    foreach ($cn as $k => $value) {
        $temp{$k}{$i} = $value;
        $values[] = &$temp{$k}{$i};
    }
}
/**
 * putting together the "types"-part for the binding of the prepared statement
 */
$types = array(str_repeat('s', count($cn) * $columnsToSearch - 1) . 's');
/**
 * merging types and references
 */
$argumentsArray = array_merge($types, $values);
/**
 * creating placeholder string for the query
 */
$placeholder = str_repeat('?, ', count($cn) - 1) . '?';

$stmt = $conn->prepare('SELECT CN_no, doc_no FROM mock_data WHERE CN_no IN (' . $placeholder . ') or doc_no IN (' . $placeholder . ')');

/**
 * check http://us3.php.net/manual/en/mysqli-stmt.bind-param.php#104073 to read what is happening here
 */
$ref = new ReflectionClass('mysqli_stmt');
$method = $ref->getMethod("bind_param");
$method->invokeArgs($stmt, $argumentsArray); 

$stmt->execute();

/**
 * fetching the result
 */
$stmt->bind_result($CN_no, $doc_no);
$row_set = array();
while ($row = $stmt->fetch()) {
    $row_set[] = array('CN_no' => $CN_no, 'doc_no' => $doc_no);
}
var_dump($row_set);
exit;

我调整了http://us3.php.net/manual/en/mysqli-stmt.bind-param.php#104073的评论,因此它符合您的情况。

顺便说一下。使用PDO作为数据库API,这将更容易编写和阅读。我稍后可能会为PDO添加一个示例。

答案 1 :(得分:2)

$mysqli = new mysqli("localhost", "my_user", "my_password", "world");

/* check connection */
if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}
// search input
$input = '42-7278954,53-1217544,07-2517487';
// create and filter your search array
$iArr = array_filter(array_map('trim', explode(",", $input)), 'strlen');
// create your search string from CN_no array 
$CN_no = implode("|",$iArr); 

/* create a prepared statement */
if ($stmt = $mysqli->prepare("SELECT * FROM `mock_data` WHERE `CN_no` RLIKE ?")) {

    /* bind parameters for search */
    $stmt->bind_param("s", $CN_no);

    /* execute query */
    $stmt->execute();
    // get all the rows returned
    // IMPORTANT
    // Use the below syntax in case you do use native mysqlnd driver.
    // If you don't have mysqlnd installed/loaded, you will get an error
    // that "mysqli_stmt_get_result()" method is undefined. 
    $result = $stmt->get_result()->fetch_all();
    // in case you don't have native mysqlnd loaded uncomment 
    // and try the below syntax to get the result
    /* $meta = $stmt->result_metadata(); 
    while ($field = $meta->fetch_field()) { 
        $params[] = &$row[$field->name]; 
    } 
    call_user_func_array(array($stmt, 'bind_result'), $params); 
    while ($stmt->fetch()) { 
        foreach($row as $key => $val) { 
            $c[$key] = $val; 
        } 
    $result[] = $c; 
    } */
    /* *********** */
    // print output
    print_r($result);

    /* close statement */
    $stmt->close();
}

/* close connection */
$mysqli->close();

答案 2 :(得分:0)

$input = '42-7278954,53-1217544,07-2517487';
$inputs = explode(',', $input);

$new_inputs = array_map(function ($item){
    $item = trim($item);
    return "'" . $item . "'";
}, $inputs);

$string = implode(',', $new_inputs);

// string is  '42-7278954','53-1217544','07-2517487'

$sql = "SELECT * FROM mock_data WHERE CN_no IN ({$string})";

答案 3 :(得分:0)

一些抽象的PHP代码:

  $cn = explode(',', $input1);
  $incn = str_repeat('?, ', count($cn)-1).'?'
  $doc = explode(',', $input2);
  $indoc = str_repeat('?, ', count($doc)-1).'?'
  $sql = "SELECT ... WHERE cn_no IN ({$incn}) or doc_no IN ({$indoc})";
  $result = $db->rows($sql, array_merge($cn, $doc));

答案 4 :(得分:0)

使用FIND_IN_SET()功能

语法:FIND_IN_SET(YOUR_INPUT_STRING_NAME,COLUMN_NAME);

YOUR_INPUT_STRING_NAME,可能是42-7278954,53-1217544,07-2517487,...

让我知道它是否对你有所帮助。

答案 5 :(得分:0)

$input = '42-7278954,53-1217544,07-2517487';

echo $strNew=str_replace(",","','",$input);

$sql = "SELECT * FROM mock_data WHERE CN_no IN ('".$strNew."')";
$row=mysqli_query($conn,$query)or die("not fire");

试试这段代码

答案 6 :(得分:0)

似乎in-clause没有通过您的实现正确生成。

要正确生成子句,您需要将用户输入拆分为数组,然后再加入列表中。例如,如果用户已将42-7278954,53-1217544,07-2517487作为输入,则列表内应如下所示:

negative

鉴于货件代码参考代码是字符串值,您必须将它们用引号括起来&#39; & #39;

以下示例可以帮助您使用implodeexplode生成列表表达式(我很少知道php)

CN_No in ( '42-7278954' , '53-1217544' , '07-2517487');

希望这有帮助。

此外,正如其他人所述,您可能需要清理用户输入以防止SQL-Injection攻击。

答案 7 :(得分:-2)

尝试

$cn = explode(',', $CN_no);
$incn = str_repeat('?, ', count($cn)-1).'?';
$doc = explode(',', $doc_no);
$indoc = str_repeat('?, ', count($doc)-1).'?';

$query = "SELECT * FROM mock_data WHERE CN_no IN ('.$incn.') or doc_no IN ({$indoc})";
$result = $conn->query($query , array_merge($incn, $indoc));

答案 8 :(得分:-3)

根据原始查询,您可以将其更改为将构建搜索数据集

$CN_no = explode(",", $CN_no);
$CN_no = "'".implode("','", $CN_no)."'";
$doc_no = explode(",", $doc_no);
$doc_no = "'".implode("','", $doc_no)."'"; 
$sql = "SELECT * FROM mock_data WHERE CN_no IN ({$CN_no}) OR doc_no IN ({$doc_no})";