我想在搜索栏中搜索一个或多个单词

时间:2017-05-22 04:42:44

标签: php sql pdo

当我输入1个单词时,我的查询总是有效,但当我输入多个单词时,查询很奇怪。它错过了相同类别的某些视频,并获得了不属于同一类别的视频。我打赌它必须做“AND”和&查询中的“或”,但我不确定。

这是我的代码。

if(isset($_GET['search']) AND !empty($_GET['search']) AND $_GET['search'] != ' ') {
    $search = htmlspecialchars($_GET['search']);
    $searchArray = explode(' ',$search);

    $videos = $stdb->prepare('SELECT id, title, videoTime FROM videos WHERE categories LIKE "skateboard" AND title LIKE "%'.implode("\" OR title LIKE \"%", $searchArray).'%" ORDER BY id DESC limit '.$start.','.$videosPerPage);
    $videos->execute();

    $totalVideosReq = $stdb->prepare('SELECT id FROM videos WHERE categories LIKE "snowboard" AND title LIKE "%'.implode("\" OR title LIKE \"%", $searchArray).'%" ORDER BY id DESC');
    $totalVideosReq->execute();
    $totalVideos = $totalVideosReq->rowcount();
    var_dump($totalVideos);
    $totalPages = ceil($totalVideos/$videosPerPage);

    $currentPage = 1;
    if(isset($_GET['page']) AND !empty($_GET['page']) AND $_GET['page'] > 0 AND $_GET['page'] <= $totalPages) {
        $_GET['page'] = intval($_GET['page']);
        $currentPage = $_GET['page'];
    } else {
        $currentPage = 1;
    }
}

有人知道,由于$searchArrayexplode()的{​​{1}},查询是否可以安全地从SQL注入?

2 个答案:

答案 0 :(得分:0)

我相信你错过了一个结束%来绕过LIKE。我想你是在追求:

$stdb->prepare('SELECT id FROM videos WHERE categories LIKE "snowboard" AND title LIKE "%'.implode("%\" OR title LIKE \"%", $searchArray).'%" ORDER BY id DESC');

答案 1 :(得分:0)

偏好问题是由OR函数的方式导致的。

if ($category == 'snowboard' AND $title == 'first_string') {
  record
} elseif ($title == 'second_string') {
  record
} ... etc

允许您执行以下单独的条件:

category = 'snowbord' AND title = 'first_string' 
OR 
category = 'ski' AND title = 'second_string'

为了将类别应用于所搜索的所有标题,您需要将OR括在括号()中,类似于PHP中的条件。

在评论中回答你的问题;使用bindParamexecute($parameters)可以提供更安全的查询。您不能传递占位符值的值数组。

例如:bindParam(':searchArray', ['Hello', 'World'])无效。

您需要为每个LIKE '%search_string%'提供单独的占位符和参数。

$search = "Hello World";
$searchArray = explode(' ', $search);

//create a like condition for each search word
$likes = rtrim(str_repeat('title LIKE ? OR ', count($searchArray)), ' OR ');

//surround each search word with '%' to find strings containing the word
$parameters = array_map(function($value) { return '%' . $value . '%'; }, $searchArray);

$query = 'SELECT id, title, videoTime 
    FROM videos 
    WHERE categories LIKE "skateboard" 
    AND (' . $likes . ')
    ORDER BY id DESC 
    LIMIT '. $start . ',' . $videosPerPage;

$videos = $stdb->prepare($query);
$videos->execute($parameters);
var_dump($query);
var_dump($parameters);

结果:https://3v4l.org/YG8Jo

#query
string(141) "SELECT id, title, videoTime 
FROM videos 
WHERE categories LIKE "skateboard" 
AND (title LIKE ? OR title LIKE ?)
ORDER BY id DESC 
LIMIT 1,20"

#parameters
array(2) {
  [0]=>
  string(7) "%Hello%"
  [1]=>
  string(7) "%World%"
}

请参阅:

此外,对于您的第二个查询,我将更改为阅读。

$query = 'SELECT COUNT(id)
    FROM videos 
    WHERE categories LIKE "snowboard" 
    AND ('. $likes .')';

$totalVideosReq = $stdb->prepare($query);
$totalVideosReq->execute($parameters);
$totalVideos = $stdb->fetchColumn();
var_dump($totalVideos);
$totalPages = ceil($totalVideos/$videosPerPage);

ORDER BY将减慢查询速度,并且您无需返回数据库中的行进行计数,因为MySQL可以为您执行此操作。

有关rowCount的参考信息,请参阅http://php.net/manual/en/pdostatement.rowcount.php#example-1049,并将其用于SELECT语句。