多次使用绑定参数

我正在尝试为我的数据库实现一个非常基本的搜索引擎,其中用户可能包含各种信息。搜索本身包含几个联合选择,其中结果总是合并为3列。


但是,返回的数据是从不同的表中获取的。


每个查询都使用$ term进行匹配,并将其绑定到“:term”作为预备参数。


现在,该手册说:


调用PDOStatement :: execute()时,对于要传递给语句的每个值,必须包含一个唯一的参数标记。您不能在准备好的语句中两次使用相同名称的命名参数标记。


我想,不是用:termX替换每个:term参数(x表示term = n ++),必须有一个更好的解决方案?


还是我只需要绑定X个:termX?


编辑为此发布我的解决方案:


$query = "SELECT ... FROM table WHERE name LIKE :term OR number LIKE :term";


$term = "hello world";

$termX = 0;

$query = preg_replace_callback("/\:term/", function ($matches) use (&$termX) { $termX++; return $matches[0] . ($termX - 1); }, $query);


$pdo->prepare($query);


for ($i = 0; $i < $termX; $i++)

    $pdo->bindValue(":term$i", "%$term%", PDO::PARAM_STR);

好了,这是一个示例。我没有时间使用sqlfiddle,但如有必要,我会在后面添加一个。


(

    SELECT

        t1.`name` AS resultText

    FROM table1 AS t1

    WHERE

        t1.parent = :userID

        AND

        (

            t1.`name` LIKE :term

            OR

            t1.`number` LIKE :term

            AND

            t1.`status` = :flagStatus

        )

)

UNION

(

    SELECT

        t2.`name` AS resultText

    FROM table2 AS t2

    WHERE

        t2.parent = :userParentID

        AND

        (

            t2.`name` LIKE :term

            OR

            t2.`ticket` LIKE :term

            AND

            t1.`state` = :flagTicket

        )

)


湖上湖
浏览 619回答 3
3回答

小怪兽爱吃肉

我已经遇到过相同的问题好几次了,我想我已经找到了一个非常简单和好的解决方案。万一我想多次使用参数,我只是将它们存储到MySQL中User-Defined Variable。这使代码更具可读性,并且您在PHP中不需要任何其他功能:$sql = "SET @term = :term";try{&nbsp; &nbsp; $stmt = $dbh->prepare($sql);&nbsp; &nbsp; $stmt->bindValue(":term", "%$term%", PDO::PARAM_STR);&nbsp; &nbsp; $stmt->execute();}catch(PDOException $e){&nbsp; &nbsp; // error handling}$sql = "SELECT ... FROM table WHERE name LIKE @term OR number LIKE @term";try{&nbsp; &nbsp; $stmt = $dbh->prepare($sql);&nbsp; &nbsp; $stmt->execute();&nbsp; &nbsp; $stmt->fetchAll();}catch(PDOException $e){&nbsp; &nbsp; //error handling}唯一的缺点可能是您需要执行其他MySQL查询-但恕我直言,这是完全值得的。由于User-Defined Variables在MySQL中是会话绑定的,因此也不必担心变量会@term在多用户环境中产生副作用。

慕容708150

我创建了两个函数来通过重命名重复使用的术语来解决该问题。一种用于重命名SQL,另一种用于重命名绑定。&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Changes double bindings to seperate ones appended with numbers in bindings array&nbsp; &nbsp; &nbsp;* example: :term will become :term_1, :term_2, .. when used multiple times.&nbsp; &nbsp; &nbsp;*&nbsp; &nbsp; &nbsp;* @param string $pstrSql&nbsp; &nbsp; &nbsp;* @param array $paBindings&nbsp; &nbsp; &nbsp;* @return array&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private function prepareParamtersForMultipleBindings($pstrSql, array $paBindings = array())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach($paBindings as $lstrBinding => $lmValue)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // $lnTermCount= substr_count($pstrSql, ':'.$lstrBinding);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preg_match_all("/:".$lstrBinding."\b/", $pstrSql, $laMatches);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $lnTermCount= (isset($laMatches[0])) ? count($laMatches[0]) : 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if($lnTermCount > 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for($lnIndex = 1; $lnIndex <= $lnTermCount; $lnIndex++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $paBindings[$lstrBinding.'_'.$lnIndex] = $lmValue;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unset($paBindings[$lstrBinding]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return $paBindings;&nbsp; &nbsp; }&nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp;* Changes double bindings to seperate ones appended with numbers in SQL string&nbsp; &nbsp; &nbsp;* example: :term will become :term_1, :term_2, .. when used multiple times.&nbsp; &nbsp; &nbsp;*&nbsp; &nbsp; &nbsp;* @param string $pstrSql&nbsp; &nbsp; &nbsp;* @param array $paBindings&nbsp; &nbsp; &nbsp;* @return string&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private function prepareSqlForMultipleBindings($pstrSql, array $paBindings = array())&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; foreach($paBindings as $lstrBinding => $lmValue)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // $lnTermCount= substr_count($pstrSql, ':'.$lstrBinding);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; preg_match_all("/:".$lstrBinding."\b/", $pstrSql, $laMatches);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $lnTermCount= (isset($laMatches[0])) ? count($laMatches[0]) : 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if($lnTermCount > 1)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $lnCount= 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $pstrSql= preg_replace_callback('(:'.$lstrBinding.'\b)', function($paMatches) use (&$lnCount) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $lnCount++;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return sprintf("%s_%d", $paMatches[0], $lnCount);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } , $pstrSql, $lnLimit = -1, $lnCount);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return $pstrSql;&nbsp; &nbsp; }用法示例:$lstrSqlQuery= $this->prepareSqlForMultipleBindings($pstrSqlQuery, $paParameters);$laParameters= $this->prepareParamtersForMultipleBindings($pstrSqlQuery, $paParameters);$this->prepare($lstrSqlQuery)->execute($laParameters);有关变量命名的说明:p:参数,l:函数str:字符串中的局部,n:数字,a:数组,m:混合
打开App,查看更多内容
随时随地看视频慕课网APP