Sintassi PHP per il risultato della funzione di dereferenziazione

sfondo

In ogni altro linguaggio di programmazione che uso regolarmente, è semplice operare sul valore di ritorno di una funzione senza dichiarare una nuova variabile per contenere il risultato della funzione.

In PHP, tuttavia, questo non sembra essere così semplice:

esempio1 (il risultato della funzione è un array)

<?php function foobar(){ return preg_split('/\s+/', 'zero one two three four five'); } // can php say "zero"? /// print( foobar()[0] ); /// <-- nope /// print( &foobar()[0] ); /// [0] ); /// <-- nope /// print( "${foobar()}[0]" ); ///  

esempio2 (il risultato della funzione è un object)

 'zero','fname'=>'homer','lname'=>'simpson',); return $vout; } // can php say "zero"? // print zoobar()->0; // {0}; // {'0'}; // {0}; // <- nope 

Qualcuno può suggerire come farlo in PHP?

    Questo è specificamente il dereferenziamento dell’array, che al momento non è supportato in php5.3, ma dovrebbe essere ansible nella prossima release, 5.4. Dereferenziazione degli oggetti è d’altra parte ansible nelle attuali versioni di PHP. Non vedo l’ora di questa funzionalità!

    PHP non può accedere ai risultati dell’array da una funzione. Alcune persone chiamano questo un problema, alcuni accettano semplicemente questo come viene progettato il linguaggio. Quindi PHP ti fa creare variabili non essenziali solo per estrarre i dati che ti servono.

    Quindi devi farlo.

     $var = foobar(); print($var[0]); 

    La distinzione tra matrici è ansible a partire da PHP 5.4:

    Esempio ( fonte ):

     function foo() { return array(1, 2, 3); } echo foo()[2]; // prints 3 

    con PHP 5.3 otterresti

     Parse error: syntax error, unexpected '[', expecting ',' or ';' 

    Risposta originale:

    Questo è stato già chiesto prima . La risposta è no. Non è ansible.

    Per citare Andi Gutmans su questo argomento:

    Questa è una richiesta di funzionalità ben nota, ma non sarà supportata in PHP 5.0. Non posso dirti se sarà mai supportato. Richiede qualche ricerca e molto pensiero.

    Puoi anche trovare questa richiesta un numero di volte nel PHP Bugtracker. Per i dettagli tecnici, ti suggerisco di controllare la RFC ufficiale e / o chiedere su PHP Internals .

    Bene, potresti utilizzare una delle seguenti soluzioni, a seconda della situazione:

     function foo() { return array("foo","bar","foobar","barfoo","tofu"); } echo(array_shift(foo())); // prints "foo" echo(array_pop(foo())); // prints "tofu" 

    Oppure puoi prendere valori specifici dall’array restituito usando list () :

     list($foo, $bar) = foo(); echo($foo); // prints "foo" echo($bar); // print "bar" 

    Modifica: il codice di esempio per ciascuno () che ho dato in precedenza non era corretto. each () restituisce una coppia chiave-valore. Quindi potrebbe essere più facile usare foreach () :

     foreach(foo() as $key=>$val) { echo($val); } 

    Sfortunatamente non c’è un modo per farlo, sebbene sia nella maggior parte degli altri linguaggi di programmazione.

    Se volessi davvero fare un solo liner, potresti fare una funzione chiamata a () e fare qualcosa del genere

     $test = a(func(), 1); // second parameter is the key. 

    Ma a parte questo, func () [1] non è supportato in PHP.

    Come altri hanno già detto, questo non è ansible. La syntax di PHP non lo consente. Tuttavia, ho un suggerimento che attacca il problema dall’altra direzione.

    Se hai il controllo del metodo getBarArray e hai accesso alla libreria standard PHP (installata su molti host PHP 5.2.X e installata per impostazione predefinita con PHP 5.3), dovresti prendere in considerazione la restituzione di un object ArrayObject invece di una matrice / raccolta PHP nativa. ArrayObjects ha un metodo offetGet , che può essere utilizzato per recuperare qualsiasi indice, quindi il tuo codice potrebbe sembrare qualcosa di simile

     append('dos'); $array->append('tres'); return $array; } } $foo = new Example(); $value = $foo->getBarArray()->offsetGet(2); 

    E se hai mai bisogno di una matrice / collezione nativa, puoi sempre trasmettere i risultati.

     //if you need $array = (array) $foo->getBarArray(); 

    Scrivi una funzione wrapper che realizzerà lo stesso. A causa del semplice type casting di PHP, questo può essere piuttosto aperto:

     function array_value ($array, $key) { return $array[$key]; } 

    Se si desidera solo restituire il primo elemento nell’array, utilizzare la funzione current ().

     return current($foo->getBarArray()); 

    http://php.net/manual/en/function.current.php

    In realtà, ho scritto una libreria che consente tale comportamento:

    http://code.google.com/p/php-preparser/

    Funziona con tutto: funzioni, metodi. Cache, quindi essere veloce quanto PHP stesso 🙂

    Non puoi concatenare espressioni come quella in PHP, quindi dovrai salvare il risultato di array_test() in una variabile.

    Prova questo:

     function array_test() { return array(0, 1, 2); } $array = array_test(); echo $array[0]; 

    Questo è troppo inverosimile, ma se hai davvero bisogno che sia in una riga:

     return index0( $foo->getBarArray() ); /* ... */ function index0( $some_array ) { return $some_array[0]; } 

    Ovviamente potresti restituire un object invece di un array e accedervi in ​​questo modo:

     echo "This should be 2: " . test()->b ."\n"; 

    Ma non ho trovato la possibilità di farlo con un array 🙁

    la mia solita soluzione è avere una funzione generica come questa

      function e($a, $key, $def = null) { return isset($a[$key]) ? $a[$key] : $def; } 

    e poi

      echo e(someFunc(), 'key'); 

    come bonus, questo evita anche l’avviso ‘indice indefinito’ quando non ne hai bisogno.

    Per quanto riguarda i motivi per cui foo()[x] non funziona, la risposta è abbastanza scortese e non verrà pubblicata qui. 😉

    Questi sono alcuni modi per affrontare il tuo problema.

    In primo luogo è ansible utilizzare il nome delle variabili direttamente se si restituisce una matrice di variabili che non fanno parte della raccolta ma hanno un significato separato ciascuna.

    Altri due modi sono per restituire il risultato che è una raccolta di valori.

     function test() { return array(1, 2); } list($a, $b) = test(); echo "This should be 2: $b\n"; function test2() { return new ArrayObject(array('a' => 1, 'b' => 2), ArrayObject::ARRAY_AS_PROPS); } $tmp2 = test2(); echo "This should be 2: $tmp2->b\n"; function test3() { return (object) array('a' => 1, 'b' => 2); } $tmp3 = test3(); echo "This should be 2: $tmp3->b\n"; 

    Estremamente ghetto, ma può essere fatto usando solo PHP. Questo utilizza una funzione lambda (che è stata introdotta in PHP 5.3). Vedi e sii stupito (e, ahem, terrificato):

     function foo() { return array( 'bar' => 'baz', 'foo' => 'bar', } // prints 'baz' echo call_user_func_array(function($a,$k) { return $a[$k]; }, array(foo(),'bar')); 

    Le lunghezze che dobbiamo attraversare per fare qualcosa di così bello nella maggior parte delle altre lingue.

    Per la cronaca, faccio qualcosa di simile a ciò che fa Nolte. Scusa se ho fatto sanguinare gli occhi a nessuno.

    Dopo ulteriori ricerche ritengo che la risposta sia no, una variabile temporanea come quella è in effetti il ​​modo canonico per gestire un array restituito da una funzione.

    Sembra che questo cambierà a partire da PHP 5.4.

    Inoltre, questa risposta era originariamente per questa versione della domanda:

    Come evitare variabili temporanee in PHP quando si utilizza un array restituito da una funzione

    Se è solo estetico, la notazione dell’object funzionerà se si restituisce un object. Per quanto riguarda la gestione della memoria, nessuna copia temporanea se effettuata, solo una modifica in riferimento.

    Risposta breve:

    Sì. È ansible operare sul valore di ritorno di una funzione in PHP, a patto che il risultato della funzione e la particolare versione di PHP lo supportino.

    Esempio di riferimento 2:

     // can php say "homer"? // print zoobar()->fname; // homer <-- yup 

    casi:

    • Il risultato della funzione è un array e la tua versione di PHP è abbastanza recente
    • Il risultato della funzione è un object e il membro dell'object desiderato è raggiungibile

    Ci sono tre modi per fare la stessa cosa:

    1. Come dice Chacha102, usa una funzione per restituire il valore dell’indice:

       function get($from, $id){ return $from[$id]; } 

      Quindi, puoi usare:

       get($foo->getBarArray(),0); 

      per ottenere il primo elemento e così via.

    2. Un modo pigro usando corrente e array_slice:

       $first = current(array_slice($foo->getBarArray(),0,1)); $second = current(array_slice($foo->getBarArray(),1,1)); 
    3. Utilizzando la stessa funzione per restituire entrambi, la matrice e il valore:

       class FooClass { function getBarArray($id = NULL) { $array = array(); // Do something to get $array contents if(is_null($id)) return $array; else return $array[$id]; } } 

      Quindi è ansible ottenere l’intero array e un singolo elemento dell’array.

       $array = $foo->getBarArray(); 

      o

       $first_item = $foo->getBarArray(0); 

    Precedentemente in PHP 5.3 dovevi fare questo:

     function returnArray() { return array(1, 2, 3); } $tmp = returnArray(); $ssecondElement = $tmp[1]; 

    Risultato: 2

    A partire da PHP 5.4 è ansible dereferenziare un array come segue:

     function returnArray() { return array(1, 2, 3); } $secondElement = returnArray()[1]; 

    Risultato: 2

    A partire da PHP 5.5:

    Puoi persino diventare intelligente:

     echo [1, 2, 3][1]; 

    Risultato: 2

    Puoi anche fare lo stesso con le stringhe. Si chiama dereferenziazione delle stringhe:

     echo 'PHP'[1]; 

    Risultato: H

    funziona?

      return ($foo->getBarArray())[0]; 

    Altrimenti, puoi pubblicare la funzione getBarArray ()? Non vedo perché non funzionerebbe da quello che hai postato finora.

    Potresti usare i riferimenti:

     $ref =& myFunc(); echo $ref['foo']; 

    In questo modo, non stai veramente creando un duplicato dell’array restituito.