duanfei1987 2019-03-16 23:20
浏览 59
已采纳

构建用于搜索的Dynamic Prepared语句

How can I alter this statement to add another search parameter such as " AND username LIKE ? " ?

Currently, searching for something on my website gives the expected results beautifully, but I'd like to search within the listing usernames too, not just the listing titles. This is the part that's giving me trouble.

The code is rather complex but I'll try to minimize the code in question only:

    $fetch_paginated_listings = "SELECT * FROM table WHERE end_date >= CURDATE() ";
    $search_param = $_GET['search'];
    $search_param = (strlen($search_param) > 175) ? substr($search_param,0,175) : $search_param; //Limit the uesr input. If users fill up the search bar, they can crash the db!

    /*Following code is to dynamically populate a prepared statement. Reference: https://www.pontikis.net/blog/dynamically-bind_param-array-mysqli*/
    $a_bind_params = explode(' ', $search_param);
    $a_param_type = array();
    foreach ($a_bind_params as $item) {
      array_push($a_param_type, 's');
      $fetch_paginated_listings .= " AND l_title LIKE ? "; //here, try to add this: " AND l_username LIKE ? " and array_push another 's' to $a_param_type
    }
    /* Bind parameters. Types: s = string, i = integer, d = double,  b = blob */
    $a_params = array();
    $param_type = '';
    $n = count($a_param_type);
    for($i = 0; $i < $n; $i++) {
      $param_type .= $a_param_type[$i];
    }
    /* with call_user_func_array, array params must be passed by reference */
    $a_params[] = & $param_type;
    for($i = 0; $i < $n; $i++) {
      /* with call_user_func_array, array params must be passed by reference */
      $a_bind_params[$i] = "%".$a_bind_params[$i]."%";
      $a_params[] = & $a_bind_params[$i];
    }

    $fetch_paginated_listings .= ' ORDER BY l_title ';    
    $fetch_paginated_listings .= ' 
    LIMIT
        ' . (($pagination->get_page() - 1) * $records_per_page) . ', ' . $records_per_page . '';

    $stmt_fetch_paginated_listings = $conn->prepare($fetch_paginated_listings);
    if($stmt_fetch_paginated_listings === false) {
      trigger_error('Wrong SQL: ' . $fetch_paginated_listings . ' Error: ' . $conn->errno . ' ' . $conn->error, E_USER_ERROR);
    }

    /* use call_user_func_array, as $stmt->bind_param('s', $param); does not accept params array */
    call_user_func_array(array($stmt_fetch_paginated_listings, 'bind_param'), $a_params);

    $stmt_fetch_paginated_listings->execute();

My attempts so far:

    foreach ($a_bind_params as $item) {
      array_push($a_param_type, 's');
      array_push($a_param_type, 's');
      $fetch_paginated_listings .= " AND l_title LIKE ? ";
      $fetch_paginated_listings .= " AND l_username LIKE ? ";
    }

^ The error it gives is "Undefined offset 3, Undefined offset 4, Undefined offset 5" perhaps because I cannot find the correct place to add the extra fields.

Lame attempt, I know, but I'm stumped. How should I do it?

EDIT:

Let's say a user types in "foo bar" in the search input field, the words "foo" and "bar" are then placed in an array with a length of 2.

1 - The query checks a column called 'title' to see if there are any matches,

2 - It also checks a column called 'username' to see if there are any matches

3 - The query is done using prepared statements for security purposes

4 - In order to achieve this type of statement (varied amount of array strings) you have to build a dynamic multiple keyword prepared statement. I used this as reference: https://www.pontikis.net/blog/dynamically-bind_param-array-mysqli

5 - I've achieved the first part of the query i.e. the query is successful for a single placeholder

6 - I'm stuck trying to search the username column, since it requires another placeholder

7 - When a user searches for "foo bar" the query should end up like this, but with placeholders: SELECT * FROM table WHERE title LIKE %foo% AND title LIKE %bar% AND username LIKE %foo% AND username LIKE %bar%

  • 写回答

2条回答 默认 最新

  • duanli9001 2019-03-17 00:59
    关注

    You were on the right track as far as you went. What you missed is how to get the right number of bind parameters. $a_bind_params has enough parameters for the title, but when you add username to it, it has to be doubled. i.e., if $a_bind_params = ['bottle','soda'], your new array needs to be ['bottle','soda','bottle','soda'] or ['bottle','bottle','soda','soda']

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 西门子S7-Graph,S7-300,梯形图
  • ¥50 用易语言http 访问不了网页
  • ¥50 safari浏览器fetch提交数据后数据丢失问题
  • ¥15 matlab不知道怎么改,求解答!!
  • ¥15 永磁直线电机的电流环pi调不出来
  • ¥15 用stata实现聚类的代码
  • ¥15 请问paddlehub能支持移动端开发吗?在Android studio上该如何部署?
  • ¥20 docker里部署springboot项目,访问不到扬声器
  • ¥15 netty整合springboot之后自动重连失效
  • ¥15 悬赏!微信开发者工具报错,求帮改