değer boş bir dizi olup olmadığını http_build_query anahtarı yok sayar.

3 Cevap

I http_build_query() için boş bir diziye ayarlanmış değer ile bir tuşa geçiyordu nerede bugün bir sorun koştu. Örneğin:

$args = array("foo", "bar", array(), "baz");
$qs = http_build_query($args);
echo $qs; // outputs 0=foo&1=bar&3=baz, I expected 0=foo&1=bar&2=&3=baz

Ben http üzerinde bir iç API için bazı verileri geçiyorum ve ben diğer tarafta tüm argümanları dışarı çekmek gerekir, çünkü bu benim için bir sorun oluşturur.

Peki, ben bu googled ve aşağıdaki hata raporu geldi: http://bugs.php.net/bug.php?id=50407. Bir yönetici dan veciz cevap "ayarı değil boş bu ayar aynıdır. Hiç hata." Olduğunu

Bu bir hata değil neden biri bana açıklayabilir misin? Herkes bir kenara bir tarafında keyfi değerini ayarlama ve diğer boş bir değer olarak bu değeri yorumlama topal kesmek gelen, geçici bir çözüm için herhangi bir fikirleri var mı?

DÜZENLEME

Ben bunun bir hata olduğunu düşünüyorum neden İşte:

$args = array("foo", "bar", array(), "baz");
$qs = http_build_query($args);
parse_str($qs, $query);
echo ($args == $query); // false, I expect it to be true

Ben belki o parse_str() düşünün ve http_build_query() birbirinin tersidir olmak naif beni sanırım.

Ben aşağıda bir cevap olarak benim şimdiki "topal hack" çözüm ilanıyla ediyorum.

3 Cevap

Can somebody explain to me why this is not a bug?

Teknik olarak, bu bir hata etiketli gerektiğini sanmıyorum. Aksine, başkalarının bu kararı veya katılmadığınızı, davranmaya tasarlanmıştır fonksiyonu sadece nasıl.

API sadece if (empty($_POST['2'])) ile kontrol edebilir

I http_build_query (bir '=' sembolü ile ekli) döndürülen sorgu dizesinde boş nesneler / diziler bırakmak reimplemented ettik. Ben de bunu varsayılan işlevselliği biraz geliştirilmiş ettik böylece tüm-içinde-all:

  • Boş nesneler ve diziler korur
  • (Yaş ile ilgili) RFC3986 için varsayılan enc_type değişti
  • Bir anahtar-değer ayırıcı argüman (varsayılan geçersiz kılmak için yeteneği '=') Eklenen
  • Sayısal endeksli anahtar-değer çiftleri için sayısal endeksleri kaldırır

Ben bir üretim ortamında (performans ya da hata hakkında hiçbir fikri) bu test değil, ve optimize değil, ama çok iyi dile getirdi.

function buildQuery($input,$numeric_prefix='',
        $arg_separator='&',$enc_type=2,
        $keyvalue_separator='=',$prefix='') {
    if ( is_array($input) ) {
        $arr = array();
        foreach ( $input as $key => $value ) {
            $name = $prefix;
            if ( strlen($prefix) ) {
                $name .= '[';
                if ( !is_numeric($key) ) {
                    $name .= $key;
                }
                $name .= ']';
            } else {
                if ( is_numeric($key) ) {
                    $name .= $numeric_prefix;
                }
                $name .= $key;
            }
            if ( (is_array($value) || is_object($value)) && count($value) ) {
                $arr[] = buildQuery($value,$numeric_prefix,
                        $arg_separator,$enc_type,
                        $keyvalue_separator,$name);
            } else {
                if ( $enc_type === 2 ) {
                    $arr[] = rawurlencode($name)
                        .$keyvalue_separator
                        .rawurlencode($value?:'');
                } else {
                    $arr[] = urlencode($name)
                        .$keyvalue_separator
                        .urlencode($value?:'');
                }
            }
        }
        return implode($arg_separator,$arr);
    } else {
        if ( $enc_type === 2 ) {
            return rawurlencode($input);
        } else {
            return urlencode($input);
        }
    }
}

Örnek:

$arr = array(
        'hello' => 'world',
        'colors' => array('red','green','blue'),
        'emptyArr' => array(),
        'nested' => array(
            'empty' => array(),
            'fruits' => array('orange','banana','apple'),
            'curly' => 'sue',
            'assoc' => array('a'=>'alpha','b'=>'bravo','c'=>'charlie')
        )
    );

echo buildQuery($arr);

Outputs: hello=world&colors%5B%5D=red&colors%5B%5D=green&colors%5B%5D=blue&emptyArr=&nested%5Bempty%5D=&nested%5Bfruits%5D%5B%5D=orange&nested%5Bfruits%5D%5B%5D=banana&nested%5Bfruits%5D%5B%5D=apple&nested%5Bcurly%5D=sue&nested%5Bassoc%5D%5Ba%5D=alpha&nested%5Bassoc%5D%5Bb%5D=bravo&nested%5Bassoc%5D%5Bc%5D=charlie I hope this finds someone well.

Bu benim şimdiki "topal hack" çözümdür. Ben iç içe diziler olasılığını hesaba vardı, bu yüzden benim örnek orijinal dizi ben soru yayınlanmıştır ne biraz farklı olduğunu unutmayın:

$args = array("foo", "bar", array("red", "blue", array(), "green"), "baz");
$original_array = $args; // save it to compare later
function replace_empty_array_with_fake_string(&$value, $key) {
    if (is_array($value)) {
        if (empty($value)) {
            $value = 'array()';
        } else {
            array_walk($value, 'replace_empty_array_with_fake_string');
        }

    }
}
array_walk($args, 'replace_empty_array_with_fake_string');
$qs = http_build_query($args);

// convert the query string back to an array, this would happen on the "other side"
parse_str($qs, $query);
function replace_fake_string_with_empty_array(&$value, $key) {
    if ($value == 'array()') {
        $value = array();
    }
    if (is_array($value)) {
        array_walk($value, 'replace_fake_string_with_empty_array');
    }
}
array_walk($query, 'replace_fake_string_with_empty_array');
echo ($original_array == $query); // true

Muhtemelen I "() dizi" yer tutucu olarak kullanmak için daha keyfi dize ile gelebilir.

Lame, biliyorum.