$ addressbits implode似乎存在问题。我手动添加了两个变量,然后用一个变量搜索以确定它不起作用,失败,然后输入两个值并且搜索工作。
经过更多的测试后,我发现如果在数组中有多个术语,则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);
答案 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 );