2012-05-05 1 views
6

Basta chiedersi se c'è un modo per aggirare questo (o se è anche possibile).Variabili variabili PHP con chiave di array

Quindi ho una sezione di codice simile a questo. Ho una stringa, con un valore che contiene parentesi quadre, simili a quelle usate quando si accede a una chiave di array. Voglio creare quella chiave di matrice stessa usando il valore delle stringhe. Spero che questo codice abbia un po 'più senso di ciò che intendo.

// String that has a value similar to an array key 
$string = 'welcome["hello"]'; 
$$string = 'thisworks'; 

// I could then print the array keys value like this 
print($welcome["hello"]); 

// This would hopefully output 'thisworks'. 

Non riesco a farlo funzionare correttamente, tuttavia. È possibile (o in quale altro modo posso farcela)?

+2

utilizzare una matrice dall'inizio, quindi non si verificano questi problemi. – hakre

+0

Stai cercando di analizzare JSON, forse? Descrivi dove questi dati provengono da un po 'di più, se tu potessi. –

+0

Non si utilizza JSON.Questa è una versione molto semplificata di ciò che sta realmente accadendo, ma in sostanza gli array multidimensionali sono usati per costruire una nuova serie di opzioni. Attualmente sto usando regexp per rilevare se la stringa contiene parentesi quadre, e se lo fa, un'istruzione if fa un sacco di cose per creare un array al di fuori di esso. Come puoi immaginare, provare a fare in modo che il metodo sopra funzionasse risparmierebbe tutto se si verifica, e funzionerebbe per entrambe le opzioni che non contengono parentesi quadre e quelle che lo fanno. –

risposta

3

Il seguente è un esempio seguente la sintassi nome della variabile che consente di risolvere i membri di matrice così:

// String that has a value similar to an array key 
$string = 'welcome["hello"]'; 

// initialize variable function (here on global variables store) 
$vars = $varFunc($GLOBALS); 

// alias variable specified by $string 
$var = &$vars($string); 

// set the variable 
$var = 'World'; 

// show the variable 
var_dump($welcome["hello"]); # string(5) "World" 

Con la seguente implementazione:

/** 
* @return closure 
*/ 
$varFunc = function (array &$store) { 
    return function &($name) use (&$store) 
    { 
     $keys = preg_split('~("])?(\\["|$)~', $name, -1, PREG_SPLIT_NO_EMPTY); 
     $var = &$store; 
     foreach($keys as $key) 
     { 
      if (!is_array($var) || !array_key_exists($key, $var)) { 
       $var[$key] = NULL; 
      } 
      $var = &$var[$key]; 
     } 
     return $var; 
    }; 
}; 

Poiché non è possibile sovraccaricare le variabili in PHP, si è limitati a esprimere iveness di PHP qui, il che significa non v'è alcun contesto di scrittura per i riferimenti variabili come valori di ritorno delle funzioni, che richiede l'aliasing aggiuntivo:

$var = &$vars($string); 

Se una cosa del genere non soddisfa le vostre esigenze, è necessario patchare PHP e se non un'opzione, PHP non offre le funzionalità linguistiche che stai cercando.

Vedere anche la domanda correlata: use strings to access (potentially large) multidimensional arrays.

+0

Grazie ancora @hakre. Lo apprezzo davvero. –

+0

Per interessi, esiste un modo simile per farlo senza l'uso di funzioni anonime? Solo per il supporto per la compatibilità all'indietro. Scusa se è una domanda stupida, questo tipo di PHP è nuovo per me (funzioni anonime, usando '&' prima delle variabili, l'uso di 'uso'). –

+0

Retrocompatibile fino a quale versione di PHP? E certo che è, puoi simulare qualsiasi chiusura con una classe. – hakre

0

È possibile utilizzare eval, anche se non lo consiglierei in un ambiente di produzione, ma ha i suoi vantaggi.

<? 
$string = 'welcome["hello"]'; 
eval('$' . $string . " = 'thisworks';"); 

// This also works : eval("$$string = 'thisworks';"); 

// I could then print the array keys value like this 
print($welcome["hello"]); // Prints 'thisworks' 
+1

ma non dimenticare una cosa. Eval è il male. – marvin

+0

Molto d'accordo, è così incredibilmente suscettibile a qualcuno che violi il contenuto all'interno della valutazione, specialmente se è dinamico e sta eseguendo qualsiasi comando che desiderano nella sceneggiatura. – Bryan

+0

Un tale peccato, perché questo sembra quasi la soluzione perfetta (che non comporta l'aggiunta di funzioni extra). Posso renderlo più sicuro usando 'call_user_func'? –

1

No, non è possibile farlo in questo modo. In alternativa, è possibile impostare la variabile di riferimento utilizzando

$welcomeHello = &$welcome["hello"] 

e quindi utilizzare

$welcomeHello = 'thisworks' 

per l'impostazione dei contenuti oggetto.

Questo sarebbe il modo più corretto e ancora più rapido per impostare gli elementi dell'array.

+0

Questo è il modo migliore –

5

In caratteri Variable variables in una stringa trattata letteralmente. Non interpretano cosa è all'interno della stringa. Quindi i caratteri [] nello $string non vengono considerati come notazione di array. Piuttosto è trattato come parte del nome della variabile.

dopo l'esecuzione $$string = 'thisworks'; PHP crea una variabile con nome welcome["hello"] letteralmente con valore impostato su thisworks.

Per stamparlo utilizzare questa notazione,

print (${'welcome["hello"]'}); 
+0

Forse una domanda stupida, ma presumo che non ci sia modo di dire a PHP di smettere di prenderlo alla lettera? –

+0

@MatthewRuddy Decisamente no. Perché ne hai bisogno così tanto? – RReverser

+0

È solo un'idea che stavo cercando di mettermi al lavoro. Ho già un'alternativa funzionante, ma un metodo simile al mio post originale ridurrebbe molte linee e sarebbe leggermente più efficiente. Mi piace sempre sperimentare modi di fare le cose meglio. –