【问题标题】:Mysql, PDO - Like statement not working using bindParamMysql,PDO - Like 语句无法使用 bindParam
【发布时间】:2012-06-15 13:35:45
【问题描述】:

我正在尝试为网站编写搜索功能代码,但在 sql 语句中遇到了类似的比较。出于某种原因,当我使用 ?和 pindparam 包含类似比较字符串的变量,它不断返回,但没有找到结果。如果我删除 ?只需输入比较 post_title LIKE '%something%' 即可。

这是我的代码:

// Retrieve search results
    function retrieve_search_posts($searchfield){
        //test the connection
        try{
            //connect to the database
            $dbh = new PDO("mysql:host=localhost;dbname=mjbox","root", "usbw");
        //if there is an error catch it here
        } catch( PDOException $e ) {
            //display the error
            echo $e->getMessage();

        }
        $searcharray = array();
        $where = "";

        $searchfield = preg_split('/[\s]+/',$searchfield);
        $total_words = count($searchfield);

        foreach($searchfield AS $key=>$searchword){
            $where .= "post_title LIKE '%".$searchword."%'";
            if($key != ($total_words - 1)){
                $where .= " OR ";
                echo $searchword . '<br>';
            }
        }
        echo $where;
        $stmt = $dbh->prepare("SELECT  p.post_id, post_year, post_desc, post_title, post_date, img_file_name, p.cat_id
                                FROM    mjbox_posts p
                                JOIN    mjbox_images i
                                ON      i.post_id = p.post_id
                                        AND i.cat_id = p.cat_id
                                        AND i.img_is_thumb = 1
                                        AND post_active = 1
                                WHERE ?
                                ORDER BY post_date
                                DESC
                                LIMIT 9");
        $stmt->bindParam(1,$where);
        $stmt->execute();

        while($row = $stmt->fetch(PDO::FETCH_ASSOC)) {

                $searcharray[] = $row;
        }

        return $searcharray;
    }


// Check for errors in search field
    function search_errors($searchfield){
        $searcherrors = array();
        if(empty($searchfield)){
            $searcherrors[] = '<p>Please enter a search term.</p>';
        }else if(strlen($searchfield)<3){
            $searcherrors[] = '<p>Your search term must be three characters or more.</p>';
        }else if(retrieve_search_posts($searchfield) == false){
            $searcherrors[] = '<p>Your search for '.$searchfield.' returned no results.</p>';
        }
        return $searcherrors;
    }

搜索.php

// Get the search terms posted 
    $searchfield = trim($_POST['searchfield']);

    // Check if there are any errors with the search terms
    $searcherrors = search_errors($searchfield);

    // If there are errors
    if(!empty($searcherrors)){
        // Display them here
        foreach($searcherrors AS $value){
            echo $value .'<br />';
        }
    }
    $searcharray = retrieve_search_posts($searchfield);


    echo '<div id="content-wrap">';
    foreach($searcharray AS $value){
        $filename = substr($value['img_file_name'],9);
        $cat_id = $value['cat_id'];
        echo '<article class="post">';
        echo '<div class="post_title">' . $value['post_title'] . '</div>';
        echo '<div class="post_info">' . 
        'Category: ' . $cat_name = get_cat_name($cat_id) .'<br />'. 
        'Year: ' . $value['post_year'] .'<br />'. 
        $value['post_desc'] .'<br />'. 
        '</div>';
        echo '<div class="link-to-post"><a href="#">Click to view</a></div>';
        echo '<a name="'.$value['post_id'].'"></a><a href="#'.$value['post_id'].'" class="linktopost"><img class="post-thumb" src="img/thumb_/'.$filename.'" alt="MJbox Michael Jackson memorabilia thumbnail" data-postid="'.$value['post_id'].'"/></a>';
        echo '<a name="'.$value['post_id'].'"></a><a href="#'.$value['post_id'].'" class="linktopost"><img class="cover-img" src="img/post-bg-1.png" alt="test" data-postid="'.$value['post_id'].'"/></a>';
        echo '</article>';

    }
    echo '</div>';

mysql 数据库中肯定有一个条目,其中包含我放入 where 字符串中的单词。当我只输入类似比较而不是使用?时,该语句在mysql查询和我的网站上都有效。

【问题讨论】:

  • 您需要将每个参数与其%符号绑定在一起。
  • $where 变量包含一个类似比较的字符串,对于搜索字段中的每个单词都会进行一个新的类似比较
  • @Brad:在所有情况下都错了。
  • @Brad:我可以看出有人没有读过这个问题。

标签: php mysql search pdo bind


【解决方案1】:

你需要单独绑定每个参数,你可以用第二个循环来做。

function retrieve_search_posts(PDO $pdo, $search_field) {
    /*
     * Get the PDO object as an argument, this function shouldn't care
     * how the PDO object is created, that's the factory's job.
     */

    /*
     * Use $underscored_names or $camelCase for variable names, easier on the eye
     */

    ## Variable initializations ##
    $where = array();

    ##Function start
    $words = preg_split("/\s+/", $search_field);

    for ($i = 0; $i < count($words); $i++) {
        /*
         * We don't need to have the word in here,
         * so we aren't even using the foreach loop, just a normal for
         */
        $where[] .= "`post_title` LIKE ?";
    }
    /*
     * For cleaner code, use an array and implode the pieces with OR,
     * this way, you don't get an OR at the beginning, nor the end.
     */
    $where_string = implode(" OR ", $where);

    $query = <<<MySQL
SELECT  p.post_id, post_year, post_desc, post_title, post_date, img_file_name, p.cat_id
    FROM mjbox_posts p
    JOIN    mjbox_images i
    ON      i.post_id = p.post_id
        AND i.cat_id = p.cat_id
        AND i.img_is_thumb = 1
        AND post_active = 1
    WHERE ?
    ORDER BY post_date DESC
    LIMIT 9
MySQL;

    $sth = $pdo->prepare($query);

    /*
    * Iterate over the array again,
    * this time, we're binding the values based on the index
    */
    foreach ($words as $index => $word) {
        $sth->bindValue($index+1, $word, PDO::PARAM_STR);
    }

    $sth->execute();

    $result = $sth->fetchAll(PDO::FETCH_ASSOC); //Fetch all the results in associative array form

    return $result;

}

查看代码中的 cmets 来解释所做的更改。

【讨论】:

  • 这会返回一个错误:Warning: PDOStatement::bindValue() [pdostatement.bindvalue]: SQLSTATE[HY093]: Invalid parameter number: Columns/Parameters are 1-based in...
  • @crm:已更正。 bindValue 从 1 开始计数。(我讨厌那些 PHP 不一致)
【解决方案2】:

您不能将字段和值绑定在一起,PDO 会将其包装在引号中,因为它假定 ? 是查询的值:

'post_title LIKE \'%something%\''

您可以保留列字段,然后绑定参数:

post_title LIKE ?

然后检查是否设置了搜索字段。使用'%'.$where.'%'绑定参数,或者如果没有输入,则只需'%'

【讨论】:

  • 啊,谢谢,因为我包含了post_title LIKE pdo 假设它是字符串的一部分,而不是 mysql 函数。谢谢。
  • 我不明白这个答案。你到底想让他做什么?
  • 他说因为我在我的字符串中包含了 mysql 关键字,所以它们被视为仅字符串语句而不是实际的 mysql 关键字。所以我必须在准备好的语句中包含post_title LIKE,并且只有字符串中的搜索词通过bindParam传递给pdo
猜你喜欢
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 2014-08-17
  • 2012-08-17
  • 2010-12-19
  • 1970-01-01
相关资源
最近更新 更多