【问题标题】:wpdb::prepare() with use multi placeholders (args)wpdb::prepare() 使用多占位符(args)
【发布时间】:2018-04-05 03:46:16
【问题描述】:

我要查询所有用户角色“订阅者”或“管理员”

$ARRAY = array('%subscriber%','%administrator%');

$query = $wpdb->prepare( "
    SELECT *
    FROM {$wpdb->usermeta}
    WHERE meta_value IN %s
    ORDER BY user_id
    DESC LIMIT {$limit} OFFSET {$offset}
",  $ARRAY );

错误:注意:wpdb::prepare 调用不正确。查询只需要一个占位符,但发送了一个包含多个占位符的数组。

我想使用多个占位符,如何解决?谢谢!

【问题讨论】:

    标签: php mysql wordpress


    【解决方案1】:

    使用 LIKE 运算符和 AND 条件代替 IN() 函数。

    你可以试试:

    $ARRAY = array('%subscriber%','%administrator%');
    
    $query = $wpdb->prepare( "
        SELECT *
        FROM {$wpdb->usermeta}
        WHERE meta_value LIKE %s OR meta_value LIKE %s
        ORDER BY user_id
        DESC LIMIT {$limit} OFFSET {$offset}
    ",  $ARRAY );
    

    【讨论】:

    • 不敢相信这已被标记为正确答案:D
    【解决方案2】:

    您需要使用 implode 函数将数组扩展为字符串,因为它期望传递一个字符串。

    $ARRAY = array('%subscriber%','%administrator%');
    $array_placeholders = implode( ', ', array_fill( 0, count( $ARRAY ), '%s' ) );
    
    $query = $wpdb->prepare( "
        SELECT *
        FROM {$wpdb->usermeta}
        WHERE meta_value IN ( $array_placeholders )
        ORDER BY user_id
        DESC LIMIT {$limit} OFFSET {$offset}
    ",  $ARRAY );
    

    【讨论】:

      【解决方案3】:

      首先,我应该指出您的查询存在安全问题。您正在寻找其中包含“订阅者”和“管理员”字样的任何元值。因此,对于您网站上的任何用户帐户,我可以将我的名字或简历设置为包含“管理员”,您的查询将把我作为一个。如果您正在寻找角色,请确保明确说明:

      $prefix = $wpdb->get_blog_prefix();
      ... "WHERE meta_key = '{$prefix}_capabilities' AND " ...
      

      第二,虽然不正确,但 Andrew 的答案看起来更好,因为您没有像在 Karlo 的答案中那样在查询本身中硬编码要查找的角色数量。假设您必须查询 15 个角色。虽然它不正确的原因是因为功能元值是一个序列化的 PHP 数组,所以很遗憾,你不能在那里真正使用IN(),但是使用相同的想法,你可以这样做:

      $prefix = $wpdb->get_blog_prefix();
      $roles = array( 'subscriber', 'administrator' );
      $parts = array();
      
      foreach ( $roles as $role ) {
          $parts []= $wpdb->prepare( "meta_value LIKE %s",
              '%' . $wpdb->esc_like( $role ) . '%' );
      }
      
      $parts_sql = implode( " OR ", $parts );
      $sql = "SELECT * FROM {$wpdb->usermeta}
          WHERE meta_key = '{$prefix}capabilities'
          AND ({$parts_sql})";
      
      $wpdb->get_results( $sql, ARRAY_A );
      

      最后,即使您确实通过这种方式获得了站点管理员,也请确保您不允许他们仅根据他们的角色进行任何操作,并在适用的情况下使用current_user_can()user_can() 运行能力检查。

      希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-07-12
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 2011-11-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多