Php 将内爆阵列加载到$wpdb prepare失败 更新1

Php 将内爆阵列加载到$wpdb prepare失败 更新1,php,wordpress,Php,Wordpress,似乎$addressbits内爆存在问题。我手动添加了两个变量,然后用其中一个进行搜索以确保它不起作用,结果失败了,然后输入了两个值,搜索成功了 更新2 经过更多的测试,我发现prepare函数消除了第二次内爆,如果它在数组中有多个项,我不确定这是否是一个bug,但它确实很烦人。我正在研究在数组创建函数中运行prepare函数以进行清理,然后将其打印到查询中 我正在wordpress网站上构建一个自定义表的搜索表单。我试图将多个术语从文本字段传递到一个数组,然后将它们传递到$wpdb->prep

似乎$addressbits内爆存在问题。我手动添加了两个变量,然后用其中一个进行搜索以确保它不起作用,结果失败了,然后输入了两个值,搜索成功了

更新2 经过更多的测试,我发现prepare函数消除了第二次内爆,如果它在数组中有多个项,我不确定这是否是一个bug,但它确实很烦人。我正在研究在数组创建函数中运行prepare函数以进行清理,然后将其打印到查询中

我正在wordpress网站上构建一个自定义表的搜索表单。我试图将多个术语从文本字段传递到一个数组,然后将它们传递到$wpdb->prepare()中进行清理。到目前为止,我的代码只适用于一个术语。。。但如果我再加上一秒钟,它就不起作用了,就好像没有为字段输入任何术语一样。我最初认为后面的逗号可能会有问题,但在trim中添加代码不起作用,我甚至用逗号连接以确保它们的存在,然后用rtrim()进行修剪,仍然不起作用。我还添加了逗号而不是trim,但仍然无法使用多个术语。我已打开错误报告,没有显示任何内容

#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);

所以你似乎有一些问题

首先,如果没有
$\u GET['address']
,那么让所有用于组装的代码都运行
$adresclean
是没有意义的-这不会有什么不同(从性能角度来看),但是将其进一步向下移动到
if(isset($\u GET['address']){/code>

第二件事是,您在几乎相同的数组上循环了两次。同样,这不是什么大问题,但除非您确实需要
$addressbits
变量,否则只需做一个循环(即使您需要,您实际上仍然可以做一个循环,只需做
$addressbits[]=$input;

第三件事是您正在使用
$wpdb->prepare()
错误。它希望您将每个替换变量作为另一个参数传递给函数。相反,您将所有
$addressbits
串联起来并作为单个变量传递,而串联
$addressclean
需要将多个参数传递给
$wpdb->prepare()
。 在foreach循环中,逃逸每个片段更容易。 如果您不想这样做,那么您可以像最初那样编写代码,只需更新这些行(它们是断章取义的,但您应该能够理解):

这将向所有$addressbits元素添加百分比,使其可以在类似于
语句的
语句中使用。正如您所见,我们在
$addressclean[]
中去掉了单引号和所有额外的百分比。 最后,我们使用
call\u user\u func\u array()
将一个参数数组传递给
$wpdb->prepare()
。请注意,它实际上接收单独的参数,而不是单个数组(如有必要,请参阅上的文档)

最后一件事是,您不需要运行一个完整的额外查询来获取结果总数。请改用
SQL\u CALC\u FOUND\u ROWS
——尽管根据您的表结构,最好运行第二个查询(尝试这两种方法,看看哪一种运行得更快)

无论如何,这是我建议的代码版本。请注意,我只是根据
post\u title
查询posts表来尝试的。我必须编写
$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 );

谢谢你的详细帖子!我昨晚很晚才意识到这一点,并得出了相同的结果。我想我刚刚通过wpdb prepare的所有标准问题示例获得了tunnel vision。感谢你对分页代码的额外建议,我还没有过多地研究它的性能方面。我的方法的唯一区别是昨晚每个人都在使用prepare,我使用了:$addressbits[]=”和
显示地址
“$wpdb->prepare(“像%%s%%”,$input);@photocode太棒了!我用
$wpdb
查看了如何摆脱LIKE语句,这只是个人喜欢使用
esc\u LIKE()
-看起来更干净,但我想可能会更让人困惑:)
#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 );