使用PHP和PDO进行SQL全文搜索

时间:2011-07-27 20:14:18

标签: php sql pdo

我正在尝试使用PHP和PDO编写简单的全文搜索。我不太确定通过SQL和PDO搜索数据库的最佳方法是什么。我找到了这个this脚本,但它是旧的MySQL扩展。我写了这个函数,女巫应该计算搜索匹配,但SQL不起作用。传入的搜索字符串如下所示:23+more+people

function checkSearchResult ($searchterm) {
    //globals
    global $lang; global $dbh_pdo; global $db_prefix;
    $searchterm = trim($searchterm);
    $searchterm = explode('+', $searchterm);
    foreach ($searchterm as $value) {
        $sql = "SELECT COUNT(*), MATCH (article_title_".$lang.", article_text_".$lang.") AGINST (':queryString') AS score FROM ".$db_prefix."_base WHERE MATCH (article_title_".$lang.", article_text_".$lang.") AGAINST ('+:queryString')";
        $sth = $dbh_pdo->prepare($sql);
        $sql_data = array('queryString' => $value);
        $sth->execute($sql_data);
        echo $sth->queryString;
        $row = $sth->fetchColumn();
        if ($row < 1) {
            $sql = "SELECT * FROM article_title_".$lang." LIKE :queryString OR aricle_text_".$lang." LIKE :queryString";
            $sth = $dbh_pdo->prepare($sql);
            $sql_data = array('queryString' => $value);
            $sth->execute($sql_data);
            $row = $sth->fetchColumn(); 
        }
    }
    //$row stays empty - no idea what is wrong
    if ($row > 1) {
        return true;
    }
    else {
        return false;
    }
}

1 个答案:

答案 0 :(得分:2)

准备$sql_data数组时,需要在参数名前加冒号:

array('queryString' => $value);

应该是:

array(':queryString' => $value);

在您的第一个SELECT中,您有AGINST而不是AGAINST

您的第二个SELECT似乎缺少FROM后的表名和WHERE子句。 LIKE参数的格式也不正确。它应该是这样的:

sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE '%:queryString%' OR aricle_text_".$lang." LIKE '%:queryString%'";

更新1&gt;&gt;

对于两个 SELECT语句,您需要为每个参数指定唯一标识符,并且LIKE通配符应放在值中,而不是语句中。所以你的第二个陈述应该是这样的:

sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE :queryString OR aricle_text_".$lang." LIKE :queryString2";

注意queryString1queryString2,不带引号或%通配符。然后,您还需要更新阵列:

$sql_data = array(':queryString1' => "%$value%", ':queryString2' => "%$value%");

有关使用具有相同值的多个参数的详细信息,请参阅PDOStatement->execute参数部分。因此,我倾向于使用问号作为占位符,而不是命名参数。我发现它更简单,更整洁,但这是一个选择问题。例如:

sql = "SELECT * FROM ".$db_prefix."_base WHERE article_title_".$lang." LIKE ? OR aricle_text_".$lang." LIKE ?";

$sql_data = array("%$value%", "%$value%");

<强>&LT;&LT;更新结束1

我不确定第二个SELECT的含义是什么,因为我认为如果第一个SELECT找不到查询值,第二个也找不到它。但我对MySQL全文搜索没有做太多,所以我可能会遗漏一些东西。

无论如何,你真的需要仔细检查SQL和任何错误。您可以通过打印PDOStatement->errorCode

的结果来获取错误信息
$sth->execute($sql_data);
$arr = $sth->errorInfo();
print_r($arr);

更新2&gt;&gt;

值得一提的另一点是:确保在将变量插入SQL语句时,只使用可信数据。也就是说,不允许用户提供的数据用于表名或列名。您使用预准备语句非常棒,但这些只保护参数,而不是SQL关键字,表名和列名。所以:

"SELECT * FROM ".$db_prefix."_base"

...正在使用变量作为表名的一部分。确保此变量包含可信数据。如果它来自用户输入,请先将其与白名单进行核对。

<强>&LT;&LT;更新结束1

您应该阅读MySQL Full-Text Search FunctionsString Comparison Functions。您需要学习如何构造基本的SQL语句,否则编写一个简单的搜索引擎将非常困难。

PHP网站上也有很多PDO示例。您可以从PDOStatement->execute的文档开始,其中包含有关如何使用该函数的一些示例。

如果您可以访问MySQL CLI,甚至是PHPMyAdmin,那么您可以在没有PHP混乱的情况下试用SQL。如果您要作为PHP应用程序的一部分进行任何数据库开发工作,您将发现能够独立于PHP测试SQL是一个很好的帮助。