Wordpress准备功能需要什么?

时间:2015-09-22 13:05:33

标签: php database wordpress

在天才功能"准备" wpdb-class(在 includes / wp-dp.php 中)我无法解释为什么isset( $args[0] )是必要的。

Alread clear是1 < func_num_args()然后第一个条目被移位。它仍然是0 < func_num_args()因此必须存在第一个条目。 $args[0]可能是NULL但是如果是这样的话,它就不能是一个数组,它会在同一个地方进行测试&#34; if&#34; if ( isset( $args[0] ) && is_array($args[0]) )

那么我错过了什么?

function prepare( $query, $args = null ) {
    if ( is_null( $query ) )
        return;

    if ( func_num_args() < 2 )
        _doing_it_wrong( 'wpdb::prepare', 'wpdb::prepare() requires at least two arguments.', '3.5' );

    $args = func_get_args();
    array_shift( $args );
    // If args were passed as an array (as in vsprintf), move them up
    if ( isset( $args[0] ) && is_array($args[0]) )
        $args = $args[0];
    $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
    $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
    $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
    $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
    array_walk( $args, array( $this, 'escape_by_ref' ) );
    return @vsprintf( $query, $args );
}

1 个答案:

答案 0 :(得分:0)

首先我不知道你得到这个代码的版本,但是在最后一个WP版本上没有func_num_args检查 - 也许你从瞬态版本when they made this fix得到了这个代码。在WP 4.3.1中,prepare函数看起来像这样:

public function prepare( $query, $args ) {
    if ( is_null( $query ) )
        return;

    // This is not meant to be foolproof -- but it will catch obviously incorrect usage.
    if ( strpos( $query, '%' ) === false ) {
        _doing_it_wrong( 'wpdb::prepare', sprintf( __( 'The query argument of %s must have a placeholder.' ), 'wpdb::prepare()' ), '3.9' );
    }

    $args = func_get_args();
    array_shift( $args );
    // If args were passed as an array (as in vsprintf), move them up
    if ( isset( $args[0] ) && is_array($args[0]) )
        $args = $args[0];
    $query = str_replace( "'%s'", '%s', $query ); // in case someone mistakenly already singlequoted it
    $query = str_replace( '"%s"', '%s', $query ); // doublequote unquoting
    $query = preg_replace( '|(?<!%)%f|' , '%F', $query ); // Force floats to be locale unaware
    $query = preg_replace( '|(?<!%)%s|', "'%s'", $query ); // quote the strings, avoiding escaped strings like %%s
    array_walk( $args, array( $this, 'escape_by_ref' ) );
    return @vsprintf( $query, $args );
}

所以让我们首先翻译代码:

if ( strpos( $query, '%' ) === false )

如果没有传递任何参数的查询,自定义错误处理程序将告诉用户他不应该使用prepare进行此类查询。

$args = func_get_args();

非常简单,它将所有参数发送到函数。它将获得具有这种结构的数组:

Array(2) (
  [0] => $query,
  [1] => $args
)

然后就在:

array_shift( $args );

这将删除$args$query)的第一个值,因此我们最终会看到一个新的数组:

Array(2) (
  [0] => $args
)

然后是嗡嗡叫你的测试:

if ( isset( $args[0] ) && is_array($args[0]) )

要理解isset为什么是必要的,让我们假设您尝试像这样调用prepare函数:

$wpdb->prepare("SELECT * FROM table WHERE arg1 = %s");

那个电话的结果是什么?该查询内部有%s,因此它将被视为有效。我们将只获得一个带有查询的参数表,在它被移位之后,我们将获得一个空数组。然后,isset将返回false,因为0索引不存在,如果in_array将被执行,它将显示以下内容错误(如果启用了通知错误显示):

Notice:  Undefined offset: 0 in ***.php on line **

这是一个说明这一点的小脚本:

function test_args($arg1, $arg2) {
    $args = func_get_args();
    echo '<b>func_get_args : </b>';
    var_dump($args);
    array_shift($args);
    echo '<b>array_shift : </b>';
    var_dump($args);
    echo '<b>isset($args[0]) : </b>';
    var_dump(isset($args[0]));
    echo '<b>is_array($args[0]) : </b>';
    var_dump(is_array($args[0]));
    echo '----<br />';
}
test_args('arg 1');

将输出以下内容:


func_get_args : array(1) {
 [0]=>
 string(5) "arg 1"
}
array_shift : array(0) {
}
isset($args[0]) : bool(false)
is_array($args[0]) : 

Notice: Undefined offset: 0 in E:\www\test-args.php on line 17

为什么isset检查有效。 虽然,因为$args不再是可选的,我们也会为prepare函数收到警告,因为我们只发送一个参数 - 这可能会在dev进程中丢失。我们错过了可选的$argsfunc_num_args检查 - 这两个以前的检查会使isset检查失效,并防止显示任何错误。这可能应该在the WP bug report报告。