将内爆阵列加载到$ wpdb准备失败

时间:2016-01-18 06:23:49

标签: php wordpress

更新1

$ addressbits implode似乎存在问题。我手动添加了两个变量,然后用一个变量搜索以确定它不起作用,失败,然后输入两个值并且搜索工作。

更新2

经过更多的测试后,我发现如果在数组中有多个术语,则prepare函数会消除第二次内爆,不确定这是否是一个错误,但确实很烦人。我正在寻找在数组创建函数中运行prepare函数来进行清理,然后将其打印到查询中。

我正在为wordpress网站中的自定义表格构建搜索表单。我正在尝试将多个术语从文本字段传递到数组,然后将它们传递到$ wpdb-> prepare()进行清理。到目前为止,我的代码正常运行完全一个词 ...但如果我添加一秒,它将无效,就好像没有为该字段输入任何条款。我最初认为它可能是尾随逗号的问题但是添加代码修剪不起作用,我甚至用逗号连接以确定它们的存在,然后用rtrim()修剪,仍然不起作用。我还添加了逗号而不是修剪,仍然失败了多个术语。我打开了错误报告,没有显示任何内容。

#explode search field values
$addressinput = explode(" ", $_GET['address']);

#create inputs for prepare
$addressbits = array();
foreach ($addressinput as $input) {
    $input = trim($input);
    if (!empty($input)) {
        $addressbits[] = $input ;
    }
}

#create prepare statements
$addressclean = array();
foreach ($addressinput as $clean) {
    $clean = trim($clean);
    if (!empty($clean)) {
        $addressclean[] = " and `display-address` LIKE '%%%s%%'";
    }
}


#if field is not empty, build and execute prepare statement, set variable
if (isset($_GET['address'])) {  
   $displayaddress = $wpdb->prepare( implode( $addressclean ) , implode(',' , $addressbits));

   }  else {

    $displayaddress = '';
  }

#query with pagination code

$customPagHTML     = "";
$query             = "select * from `record-display` where" . $code . $displayaddress . $format  . $name . " ORDER BY `date` DESC";
$total_query     = "SELECT COUNT(1) FROM (${query}) AS combined_table";
$total             = $wpdb->get_var( $total_query );
$items_per_page = 10;
$page             = isset( $_GET['cpage'] ) ? abs( (int) $_GET['cpage'] ) : 1;
$offset         = ( $page * $items_per_page ) - $items_per_page;
$result         = $wpdb->get_results( $query . "  LIMIT ${offset}, ${items_per_page}", ARRAY_A );
$totalPage         = ceil($total / $items_per_page);

1 个答案:

答案 0 :(得分:1)

所以你似乎有一些问题。

首先,如果没有$adressclean,那么组装$_GET['address']的所有代码都没有意义 - 它不会产生任何影响(性能明智),但它会更有意义将其进一步向下移动到if ( isset( $_GET['address'] ) ) {

第二件事是你在两次相同的数组上循环。再一次 - 并不是什么大不了的事,但除非你真的需要$addressbits变量,否则只需做一个循环(即使你需要它,你实际上仍然可以做一个循环,只做$addressbits[] = $input;

第三件事是你错误地使用$wpdb->prepare()。它期望您将每个替换变量作为另一个参数传递给该函数。相反,您将所有$addressbits连接起来并将它们作为单个变量传递,而连接$addressclean则需要将多个参数传递给$wpdb->prepare()。 逃离foreach循环内的每个片段更容易。 如果您不想这样做,那么您可以像最初那样编写代码,只需更新这些代码(它们将脱离上下文,但您应该能够弄清楚):

$addressbits[] = '%' . $wpdb->esc_like( $input ) . '%';

$addressclean[] = " and `display-address` LIKE %s";

$prepare_params = $addressbits;
array_unshift( $prepare_params, implode( $addressclean ) ); 
$displayaddress = call_user_func_array( array( $wpdb, 'prepare', implode( $addressclean ), $addressbits );

这将为所有$ addressbits元素添加百分比,使其可以在LIKE语句中使用。如您所见,我们在$addressclean[]中删除了单引号和所有额外百分比。 最后,我们使用call_user_func_array()将参数数组传递给$wpdb->prepare()。请注意,它实际上接收单独的参数,而不是单个数组(如果需要,请查看call_user_func_array()上的文档)。

最后一件事是您不需要运行完整的额外查询来获取结果总数。请改用SQL_CALC_FOUND_ROWS - 尽管取决于您的表格结构,但最好再运行第二个查询(尝试这两种方法,看看哪个方法运行得更快)。

无论如何,这是我建议的代码版本。请注意,我只是通过查询基于post_title的帖子表来尝试它。我不得不弥补$code$format$name,因为您没有在代码中包含它们。

#if field is not empty, build and execute prepare statement, set variable
if ( isset( $_GET['address'] ) ) {
    #explode search field values
    $addressinput = explode( ' ', $_GET['address'] );
    #create inputs for prepare
    $addressclean = array();
    foreach ( $addressinput as $input ) {
        $input = trim( $input );
        if ( ! empty( $input ) ) {
            $addressclean[] = $wpdb->prepare( '`display-address` LIKE %s', '%' . $wpdb->esc_like( $input ) . '%' );
        }
    }

    $displayaddress = $addressclean ? ' AND ( ' . implode( ' AND ', $addressclean ) . ' ) ' : '';
}  else {
    $displayaddress = '';
}

#query with pagination code
$items_per_page = 10;
$page           = isset( $_GET['cpage'] ) ? absint( $_GET['cpage'] ) : 1;
$offset         = ( $page * $items_per_page ) - $items_per_page;

$customPagHTML  = "";
$query          = "SELECT SQL_CALC_FOUND_ROWS * FROM `record-display` 
    WHERE $code
        $displayaddress
        $format
        $name
    GROUP BY {$wpdb->posts}.ID
    ORDER BY `post_date` DESC
    LIMIT {$offset}, {$items_per_page}";
$result      = $wpdb->get_results( $query, ARRAY_A );
$total       = $wpdb->get_var( "SELECT FOUND_ROWS()" );
$totalPage   = ceil( $total / $items_per_page );