2010-11-04 14 views
80

È possibile utilizzare una stringa numerica come "123" come chiave in un array PHP, senza che venga convertita in un numero intero?Una stringa numerica come chiave di array in PHP

$blah = array('123' => 1); 
var_dump($blah); 

stampe

array(1) { 
    [123]=> 
    int(1) 
} 

voglio

array(1) { 
    ["123"]=> 
    int(1) 
} 
+7

Dal momento che PHP è tipicamente digitato, '" 123 "' == '123' per quasi tutti gli scopi. Qual è il motivo per cui lo vuoi specificamente come stringa (e avere un int è cattivo)? – ircmaxell

+8

La ragione che mi viene in mente riguarda le funzioni di array come 'array_merge' *" Se gli array di input hanno le stesse chiavi di stringa, il valore successivo per quella chiave sovrascriverà quello precedente. Se, ** tuttavia, gli array contengono numeri keys **, il valore successivo non sovrascriverà il valore originale, ma verrà aggiunto. "* – ficuscr

+6

Un altro esempio in cui le stringhe numeriche come chiavi di array sono problematiche: [' asort'] (http://php.net/manual/en /function.asort.php) – swenedo

risposta

68

No; no, non è:

Da the manual:

Una chiave può essere un numero intero o una stringa. Se una chiave è la rappresentazione standard di un intero, verrà interpretata come tale (ad esempio "8" verrà interpretato come 8, mentre "08" sarà interpretato come "08").

Addendum

A causa dei commenti qui sotto, ho pensato che sarebbe stato divertente per sottolineare che il comportamento è simile ma non identico alle chiavi oggetto JavaScript.

foo = { '10' : 'bar' }; 

foo['10']; // "bar" 
foo[10]; // "bar" 
foo[012]; // "bar" 
foo['012']; // undefined! 
+22

... * shudders * ... – jameshfisher

+69

PHP, l'IE lato server. –

+5

Sembra che ci sia un modo, in realtà! Non sei d'accordo con questa risposta? http://stackoverflow.com/a/35180513/247696 – Flimm

5

È possibile typecast la chiave per una stringa, ma alla fine sarà convertito in un intero a causa di loose-tipizzazione di PHP. Guardate voi stessi:

$x=array((string)123=>'abc'); 
var_dump($x); 
$x[123]='def'; 
var_dump($x); 

Dal manuale PHP:

Una chiave può essere un numero intero o una stringa. Se una chiave è la rappresentazione standard di un intero, verrà interpretata come tale (ad esempio "8" verrà interpretato come 8, mentre "08" sarà interpretato come "08"). I float in chiave sono troncati a numero intero. I tipi di array indicizzati e associativi sono dello stesso tipo in PHP, che può contenere sia indici interi che stringhe.

+1

La conversione non è dovuta a errori di digitazione; php determina se la stringa * sembra * numerica e poi la converte. –

+0

Quindi stai dicendo che non è possibile? [Questa risposta] (http://stackoverflow.com/a/35180513/247696) mostra che esiste un modo per usare una stringa che assomiglia ad un intero come una chiave in una matrice. – Flimm

+0

IMHO il problema è l'interprete PHP. Non è nemmeno possibile immaginare di avere un linguaggio che mischia stringhe e interi come chiavi di array. La migliore soluzione? Come proposto da Undolog http://stackoverflow.com/a/15413637/1977778 la soluzione migliore è utilizzare uno spazio finale ... Purtroppo. – sentenza

12

Se è necessario utilizzare un tasto numerico in una struttura dati php, un oggetto funzionerà. E gli oggetti preservano l'ordine, quindi puoi eseguire l'iterazione.

$obj = new stdClass(); 
$key = '3'; 
$obj->$key = 'abc'; 
+0

Questo è un ottimo suggerimento. Sto scrivendo codice framework e mi trovo di fronte a qualcuno che passa una matrice che potrebbe avere indicizzazione "accidentale": array ('this', 'that') o indexing "associativo": array (123 => array ('this', 'that ')). Ora, grazie a te, posso solo digitare hint;) +1 –

+0

Ma è possibile utilizzare una stringa numerica come "123" come una chiave in un array PHP, senza che venga convertita in un numero intero? – Flimm

+0

@Flimm no che non è possibile, ed è per questo che offro la mia soluzione. – steampowered

0

Mi sono imbattuto in questo problema su un array con "0" e "" come chiavi. Significava che non potevo controllare le chiavi dell'array con == o ===.

$array=array(''=>'empty', '0'=>'zero', '1'=>'one'); 
echo "Test 1\n"; 
foreach ($array as $key=>$value) { 
    if ($key == '') { // Error - wrongly finds '0' as well 
     echo "$value\n"; 
    } 
} 
echo "Test 2\n"; 
foreach ($array as $key=>$value) { 
    if ($key === '0') { // Error - doesn't find '0' 
     echo "$value\n"; 
    } 
} 

La soluzione alternativa consiste nel restituire le chiavi di array alle stringhe prima dell'uso.

echo "Test 3\n"; 
foreach ($array as $key=>$value) { 
    if ((string)$key == '') { // Cast back to string - fixes problem 
     echo "$value\n"; 
    } 
} 
echo "Test 4\n"; 
foreach ($array as $key=>$value) { 
    if ((string)$key === '0') { // Cast back to string - fixes problem 
     echo "$value\n"; 
    } 
} 
+1

Questa non è davvero una risposta alla domanda. – Flimm

8

La mia soluzione è:

$id = 55; 
$array = array(
    " $id" => $value 
); 

Lo spazio char (prepend) è una buona soluzione, perché mantenere la conversione int:

foreach($array as $key => $value) { 
    echo $key; 
} 

Vedrai 55 come int.

+3

Oppure '" 0 $ id "=> $ valore'. Anche la prepending con '0' funziona. – nawfal

+0

@nawfal grazie amico, non mi aspettavo di trovare la risposta qui sotto – Va1iant

+0

Quindi stai dicendo che non è possibile usare una stringa numerica come "123" come una chiave in un array PHP, senza che sia convertita in un intero? – Flimm

0

Ho riscontrato questo problema nel tentativo di unire matrici che includevano sia chiavi stringa sia numeri interi. Era importante che anche i numeri interi venissero gestiti come stringa poiché questi erano nomi per campi di input (come nelle dimensioni delle scarpe ecc.)

Quando ho usato $data = array_merge($data, $extra); PHP avrebbe "riordinato" le chiavi. Nel tentativo di fare l'ordine, le chiavi intere (ho provato con 6-'6' - "6" anche (string)"6" come chiavi) ha ottenuto rinominato 0-n ... Se ci pensate, nella maggior parte dei casi, questo sarebbe il comportamento desiderato.

È possibile aggirare il problema utilizzando $data = $data + $extra;. Piuttosto semplice, ma all'inizio non ci ho pensato ^^.

+0

Lo stesso identico problema mi ha portato a questa pagina, ma devo dire che questa non è la risposta alla domanda dell'OP. – Flimm

+0

@Flimm True. Ma la ricerca di una risposta mi ha portato a questa pagina. Ho pensato che la mia soluzione potesse essere di aiuto per altri googler :) – Brainfeeder

-1

Ho avuto questo problema durante il tentativo di ordinare un array in cui avevo bisogno che la chiave di ordinamento fosse un hex sha1. Quando un valore sha1 risultante non ha lettere, PHP trasforma la chiave in un numero intero. Ma avevo bisogno di ordinare la matrice sull'ordine relativo delle stringhe. Quindi avevo bisogno di trovare un modo per forzare la chiave ad essere una stringa senza modificare l'ordinamento.

Guardando il grafico ASCII (https://en.wikipedia.org/wiki/ASCII) il punto esclamativo ordina all'incirca lo stesso spazio e sicuramente inferiore a tutti i numeri e le lettere.

Quindi ho aggiunto un punto esclamativo alla fine della stringa di chiavi.

for(...) { 

    $database[$sha.'!'] = array($sha,$name,$age); 
} 

ksort($database); 
$row = reset($database); 
$topsha = $row[0]; 
+0

Quindi stai dicendo che non è possibile usare una stringa numerica come "123" come chiave in un array PHP, senza che venga convertita in un intero? – Flimm

+0

No: tratta solo la chiave che rappresenta tutti i numeri come un numero intero quando si ordina l'array usando ksort() - non viene mai convertito in un numero intero - solo confrontato come uno durante l'ordinamento. – drchuck

25

Sì, è possibile per array-esprimono un stdClass oggetto:

$data = new stdClass; 
$data->{"12"} = 37; 
$data = (array) $data; 
var_dump($data); 

Che ti dà (fino a PHP versione 7.1):

array(1) { 
    ["12"]=> 
    int(37) 
} 

(Aggiornamento: il mio originale risposta ha mostrato un modo più complicato utilizzando json_decode() e json_encode() che non è necessario.)

Nota il commento: Purtroppo non è possibile fare riferimento direttamente al valore: $data['12'] genererà un avviso.

Aggiornamento:
Da PHP 7.2 a è anche possibile utilizzare una stringa numerica come chiave per fare riferimento al valore:

var_dump($data['12']); // int 32 
+1

L'accesso diretto al valore con una chiave stringa non funziona, però. Aggiungi questa linea al tuo esempio: 'echo $ data ['12 '];'. Fornirà l'errore "Avviso: Offset non definito: 12 in - on line 5". –

+0

Sì, hai ragione. Supponendo che fosse possibile a volte in passato. – David

+0

quando U usa laravel dd ($ data) si bloccherà: P –

1

stringhe contenenti numeri interi validi saranno gettati al tipo intero . Per esempio. il tasto "8" verrà effettivamente memorizzato sotto 8. D'altra parte "08" non verrà lanciato, in quanto non è un numero intero decimale valido.

SBAGLIATO

Ho una funzione di fusione che gestisce sequenziale a associativa fusione array,

$array_assoc = cast($arr,'array_assoc'); 

$array_sequential = cast($arr,'array_sequential'); 

$obj = cast($arr,'object'); 

$json = cast($arr,'json'); 



function cast($var, $type){ 

    $orig_type = gettype($var); 

    if($orig_type == 'string'){ 

     if($type == 'object'){ 
      $temp = json_decode($var); 
     } else if($type == 'array'){ 
      $temp = json_decode($var, true); 
     } 
     if(isset($temp) && json_last_error() == JSON_ERROR_NONE){ 
      return $temp; 
     } 
    } 
    if(@settype($var, $type)){ 
     return $var; 
    } 
    switch($orig_type) { 

     case 'array' : 

      if($type == 'array_assoc'){ 

       $obj = new stdClass; 
       foreach($var as $key => $value){ 
        $obj->{$key} = $value; 
       } 
       return (array) $obj; 

      } else if($type == 'array_sequential'){ 

       return array_values($var); 

      } else if($type == 'json'){ 

       return json_encode($var); 
      } 
     break; 
    } 
    return null; // or trigger_error 
} 
0

Per quanto riguarda la soluzione @ Davide, si prega di notare che quando si tenta di accedere ai valori di stringa in l'array associativo, i numeri non funzioneranno.La mia ipotesi è che siano castate su interi dietro le quinte (quando si accede alla matrice) e non viene trovato alcun valore. Anche l'accesso ai valori come numeri interi non funzionerà. Ma puoi usare array_shift() per ottenere i valori o iterare la matrice.

$data = new stdClass; 
$data->{"0"} = "Zero"; 
$data->{"1"} = "One"; 
$data->{"A"} = "A"; 
$data->{"B"} = "B"; 

$data = (array)$data; 

var_dump($data); 
/* 
Note the key "0" is correctly saved as a string: 
array(3) { 
    ["0"]=> 
    string(4) "Zero" 
    ["A"]=> 
    string(1) "A" 
    ["B"]=> 
    string(1) "B" 
} 
*/ 

//Now let's access the associative array via the values 
//given from var_dump() above: 
var_dump($data["0"]); // NULL -> Expected string(1) "0" 
var_dump($data[0]); // NULL (as expected) 
var_dump($data["1"]); // NULL -> Expected string(1) "1" 
var_dump($data[1]); // NULL (as expected) 
var_dump($data["A"]); // string(1) "A" (as expected) 
var_dump($data["B"]); // string(1) "B" (as expected) 
Problemi correlati