Più ritorni da una funzione


198

È possibile avere una funzione con due ritorni come questo:

function test($testvar)
{
  // Do something

  return $var1;
  return $var2;
}

In tal caso, come potrei ottenere ogni reso separatamente?


1
Cosa stai cercando di realizzare esattamente? Sicuramente se spiegassi il tuo vero problema, qualcuno qui potrebbe aiutarti a trovare una soluzione elegante.
Mike Daniels,

3
La domanda non fa distinzione tra uno o due dei due valori, entrambi due dei due valori o una valutazione pigra di un nuovo concetto, quindi probabilmente due dei due valori. Il primo è banale con qualsiasi tipo di flusso condizionale. Il secondo è consentito in Python: q, r = divmod (x, y); così come Lisp; PHP richiede l'elenco ($ q, $ r) = twovals (); hack, dove function twovals () {return array ($ a, $ b); }. La valutazione pigra è piuttosto avanzata e non ha ancora preso piede in PHP. Poiché la domanda non è precisa, si consiglia di non utilizzare questa voce come riferimento definitivo per questo argomento.
DragonLord,

5
Se sono necessari entrambi i valori, restituirli in un array.
Bhargav Nanekalva,

2
@DragonLord in PHP 7.1, puoi usare la sintassi dell'elenco breve
Janus Troelsen

1
C'è una domanda duplicata, ma con risposte più concise, ti porterà più velocemente al punto: restituire 2 valori da una funzione .
Gras Double

Risposte:


162

Non è possibile restituire 2 variabili. Tuttavia, è possibile propagare un array e restituirlo; creare un condizionale per restituire una variabile dinamica, ecc.

Ad esempio, questa funzione ritornerebbe $var2

function wtf($blahblah = true) {
    $var1 = "ONe";
    $var2 = "tWo";

    if($blahblah === true) {
      return $var2;
    }
    return $var1;
}

In applicazione:

echo wtf();
//would echo: tWo
echo wtf("not true, this is false");
//would echo: ONe

Se li volevi entrambi, potresti modificare un po 'la funzione

function wtf($blahblah = true) {
    $var1 = "ONe";
    $var2 = "tWo";

    if($blahblah === true) {
      return $var2;
    }

    if($blahblah == "both") {
      return array($var1, $var2);
    }

    return $var1;
}

echo wtf("both")[0]
//would echo: ONe
echo wtf("both")[1]
//would echo: tWo

list($first, $second) = wtf("both")
// value of $first would be $var1, value of $second would be $var2

15
Se solo PHP avesse avuto Perlwantarray()
Marc B il

6
IMHO questa risposta sarebbe migliorata se omettesse la prima parte, che discute su come restituire uno o un valore diverso, a seconda di una condizione. Sono certo che il 99,999+% delle persone che partecipano a questa discussione vogliono sapere come restituire entrambi i valori contemporaneamente. Vedi la risposta più votata.
ToolmakerSteve

401

Tecnicamente, non puoi restituire più di un valore. Tuttavia, esistono diversi modi per aggirare tale limitazione. Il modo in cui agisce di più come restituire più valori è con la listparola chiave:

function getXYZ()
{
    return array(4,5,6);
}

list($x,$y,$z) = getXYZ();

// Afterwards: $x == 4 && $y == 5 && $z == 6
// (This will hold for all samples unless otherwise noted)

Tecnicamente, stai restituendo un array e lo usi listper memorizzare gli elementi di quell'array in valori diversi invece di archiviare l'array effettivo. L'uso di questa tecnica ti farà sentire come se restituissi più valori.

La listsoluzione è piuttosto specifica per php. Ci sono alcune lingue con strutture simili, ma più lingue che non lo fanno. C'è un altro modo comunemente usato per "restituire" più valori ed è disponibile in quasi tutte le lingue (in un modo o nell'altro). Tuttavia, questo metodo apparirà piuttosto diverso, quindi potrebbe essere necessario abituarsi.

// note that I named the arguments $a, $b and $c to show that
// they don't need to be named $x, $y and $z
function getXYZ(&$a, &$b, &$c)
{
    $a = 4;
    $b = 5;
    $c = 6; 
}

getXYZ($x, $y, $z);

Questa tecnica è utilizzata anche in alcune funzioni definite da php stesso (ad es. $countIn str_replace , $matchesin preg_match ). Questo potrebbe sembrare molto diverso dal restituire più valori, ma vale la pena almeno saperlo.

Un terzo metodo consiste nell'utilizzare un oggetto per contenere i diversi valori necessari. Questo è più digitazione, quindi non è usato abbastanza spesso come i due metodi sopra. Può essere logico utilizzarlo, tuttavia, quando si utilizza lo stesso insieme di variabili in un numero di posizioni (o, naturalmente, lavorando in una lingua che non supporta i metodi di cui sopra o che consente di farlo senza digitare extra).

class MyXYZ
{
    public $x;
    public $y;
    public $z;
}

function getXYZ()
{
    $out = new MyXYZ();

    $out->x = 4;
    $out->y = 5;
    $out->z = 6;

    return $out;
}

$xyz = getXYZ();

$x = $xyz->x;
$y = $xyz->y;
$z = $xyz->z;

I metodi sopra descritti riassumono i modi principali per restituire più valori da una funzione. Tuttavia, ci sono variazioni su questi metodi. Le varianti più interessanti da guardare sono quelle in cui stai effettivamente restituendo un array, semplicemente perché c'è così tanto che puoi fare con gli array in PHP.

Innanzitutto, possiamo semplicemente restituire un array e non trattarlo come altro che un array:

function getXYZ()
{
    return array(1,2,3);
}

$array = getXYZ();

$x = $array[1];
$y = $array[2];
$z = $array[3];

La parte più interessante del codice sopra è che il codice all'interno della funzione è lo stesso del primo esempio che ho fornito; è cambiato solo il codice che chiama la funzione. Ciò significa che dipende da chi chiama la funzione come trattare il risultato restituito dalla funzione.

In alternativa, si potrebbe usare un array associativo:

function getXYZ()
{
    return array('x' => 4,
                 'y' => 5,
                 'z' => 6);
}

$array = getXYZ();

$x = $array['x'];
$y = $array['y'];
$z = $array['z'];

Php ha la compactfunzione che ti permette di fare come sopra ma mentre scrivi meno codice. (Beh, l'esempio non avrà meno codice, ma probabilmente un'applicazione del mondo reale.) Tuttavia, penso che la quantità di salvataggio della digitazione sia minima e rende il codice più difficile da leggere, quindi non lo farei da solo. Tuttavia, ecco un esempio:

function getXYZ()
{
    $x = 4;
    $y = 5;
    $z = 6;

    return compact('x', 'y', 'z');
}

$array = getXYZ();

$x = $array['x'];
$y = $array['y'];
$z = $array['z'];

Va notato che mentre compactha una controparte inextract che potrebbe essere utilizzata nel codice chiamante qui, ma poiché è una cattiva idea usarlo (specialmente per qualcosa di così semplice) non ne darò nemmeno un campione. Il problema è che farà "magia" e creerà variabili per te, mentre non puoi vedere quali variabili vengono create senza andare in altre parti del codice.

Infine, vorrei menzionare che listnon funziona davvero bene con l'array associativo. Quanto segue farà ciò che ti aspetti:

function getXYZ()
{
    return array('x' => 4,
                 'y' => 5,
                 'z' => 6);
}

$array = getXYZ();

list($x, $y, $z) = getXYZ();

Tuttavia, quanto segue farà qualcosa di diverso:

function getXYZ()
{
    return array('x' => 4,
                 'z' => 6,
                 'y' => 5);
}

$array = getXYZ();

list($x, $y, $z) = getXYZ();

// Pay attention: $y == 6 && $z == 5

Se hai usato listun array associativo e qualcun altro deve cambiare il codice nella funzione chiamata in futuro (che potrebbe accadere in qualsiasi situazione), potrebbe improvvisamente rompersi, quindi sconsiglierei di combinarlo listcon array associativi.


2
Inoltre: return compact ('var1', 'var2', 'var3');
bjudson,

1
Questa è un'altra opzione, ma non mi sembra di restituire più valori, proprio come restituire un array. Ma potrei essere io. Personalmente, troverei return array('x' => $x, 'y' => $y, 'z' => $z)più pulito, ma al punto in cui lo scriverei da solo, non al punto in cui chiederei agli altri di usare quel formato.
Jasper,

2
L'uso di List () è un'ottima risposta a un problema simile che ho avuto. questo è un modo eccellente per validare e restituire più variabili in una funzione. una rapida occhiata ai documenti php farà luce su questa funzione e forse la renderà più chiara. php.net/manual/en/function.list.php .. grazie Jasper!
Giustino,

2
+1 per una risposta così ampia, in particolare a una domanda così ampia e generale. Nonostante ciò, questa risposta mi ha aiutato immensamente.
Lee Blake,

2
@Mikey Ragioni storiche. Questa risposta è stata originariamente pubblicata su una domanda diversa, che è stata eliminata per essere un duplicato esatto di questa (nonostante fosse effettivamente più vecchia). La risposta è stata spostata su questa domanda dopo l'ultima visita di colui che ha posto questa domanda.
Jasper,

73

Nel tuo esempio, il secondo ritorno non accadrà mai: il primo ritorno è l'ultima cosa che PHP eseguirà. Se è necessario restituire più valori, restituire un array:

function test($testvar) {

    return array($var1, $var2);
}

$result = test($testvar);
echo $result[0]; // $var1
echo $result[1]; // $var2

18
Puoi anche fare:list($result_1, result_2) = test($testvar);
Tim Cooper

@Tim Cooper: result_2o $result_2?
Peter Mortensen,

@PeterMortensen:$result_2
Tim Cooper

46

Da PHP 7.1 abbiamo una corretta destrutturazione per gli elenchi. Quindi puoi fare cose come questa:

$test = [1, 2, 3, 4];
[$a, $b, $c, $d] = $test;
echo($a);
> 1
echo($d);
> 4

In una funzione questo sarebbe simile a questo:

function multiple_return() {
    return ['this', 'is', 'a', 'test'];
}

[$first, $second, $third, $fourth] = multiple_return();
echo($first);
> this
echo($fourth);
> test

La distruzione è uno strumento molto potente. È in grado di distruggere anche le coppie chiave => valore:

["a" => $a, "b" => $b, "c" => $c] = ["a" => 1, "b" => 2, "c" => 3];

Dai un'occhiata alla nuova pagina delle funzionalità di PHP 7.1:

Nuove caratteristiche


5
Vorrei che StackOverflow avesse una funzione come 'risposta in primo piano' anche quando non è accettata al momento della creazione della domanda perché questa risposta qui è abbastanza utile e aggiornata, ma ovviamente è fuori tema.
Jonatas CD

3
@JonatasCD - non so perché dici che questa risposta è "off-topic". In php 7.1 è il modo più conveniente per creare e gestire più valori di ritorno da una funzione. Quindi, per le nuove versioni di php, è una risposta superiore alla risposta originale accettata.
ToolmakerSteve

@ToolmakerSteve Penso che tu mi abbia frainteso. "fuori tema" alla domanda era il mio suggerimento di poter cambiare quella che era la domanda accettata sulla base di future implementazioni. Non è stato nulla contro la tua risposta;)
Jonatas CD

@JonatasCD - Ahh, questo lo spiega. (Non è la mia risposta, ero solo perplesso.) Almeno un tag che dice "questo è più aggiornato della risposta accettata" Forse tre persone devono essere d'accordo con quel tag, e poi diventa in primo piano. :)
ToolmakerSteve

26

In PHP 5.5 c'è anche un nuovo concetto:, in generatorscui puoi produrre più valori da una funzione:

function hasMultipleValues() {
    yield "value1";
    yield "value2";
}

$values = hasMultipleValues();
foreach ($values as $val) {
    // $val will first be "value1" then "value2"
}

16

Oppure puoi passare per riferimento:

function byRef($x, &$a, &$b)
{
    $a = 10 * $x;
    $b = 100 * $x;
}

$a = 0;
$b = 0;

byRef(10, $a, $b);

echo $a . "\n";
echo $b;

Ciò produrrebbe

100
1000

9

So di essere in ritardo, ma esiste una soluzione semplice e piacevole per questo problema.
È possibile restituire più valori contemporaneamente utilizzando la destrutturazione.

function test()
{
    return [ 'model' => 'someValue' , 'data' => 'someothervalue'];
}

Ora puoi usare questo

$result = test();
extract($result);

extractcrea una variabile per ciascun membro dell'array, che prende il nome da quel membro. È quindi ora possibile accedere $modele$data


1
NOTA: fare attenzione che le chiavi (qui modele data) non esistano già come variabili. In tal caso, utilizzare il prefixparametro di extractper evitare conflitti.
ToolmakerSteve

7

È possibile restituire più matrici e scalari da una funzione

function x()
{
    $a=array("a","b","c");
    $b=array("e","f");
    return array('x',$a,$b);
}

list ($m,$n,$o)=x();

echo $m."\n";
print_r($n);
print_r($o);

7

Non è possibile avere due dichiarazioni di reso. Tuttavia non genera errori ma quando viene chiamata la funzione riceverai solo il primo valore dell'istruzione return. Possiamo usare return of array per ottenere più valori in cambio. Per esempio:

function test($testvar)
{
  // do something
  //just assigning a string for example, we can assign any operation result
  $var1 = "result1";
  $var2 = "result2";
  return array('value1' => $var1, 'value2' => $var2);
}

5

Le funzioni, per definizione, restituiscono solo un valore.

Tuttavia, come hai ipotizzato, quel valore può essere un array.

Quindi puoi sicuramente fare qualcosa del tipo:

<?PHP
function myfunc($a,$b){
   return array('foo'=>$a,'bar'=>$b);
}
print_r(myfunc('baz','bork'));

Detto questo, vale la pena prendersi un momento e pensare a tutto ciò che stai cercando di risolvere. Mentre restituire un valore di risultato complesso (come un array o un oggetto) è perfettamente valido, se stai pensando che "Voglio restituire due valori", potresti progettare male. Senza ulteriori dettagli nella tua domanda, è difficile da dire, ma non fa mai male fermarsi e pensare due volte.


5

È consigliabile mettere le variabili restituite nell'array e quindi utilizzarle list()per assegnare i valori dell'array alle variabili.

<?php

function add_subt($val1, $val2) {
    $add = $val1 + $val2;
    $subt = $val1 - $val2;

    return array($add, $subt);
}

list($add_result, $subt_result) = add_subt(20, 7);
echo "Add: " . $add_result . '<br />';
echo "Subtract: " . $subt_result . '<br />';

?>

5

Sì, puoi usare un oggetto :-)

Ma il modo più semplice è restituire un array:

return array('value1', 'value2', 'value3', '...');

5

Per PHP 7.1 <= puoi usare la nuova sintassi (invece della funzione list ):

/**
* @return  array  [foo, bar]
*/
function getFooAndBar(): array {
    return ['foo', 'bar'];
}

[$foo, $bar] = getFooAndBar();

print 'Hello '. $foo . ' and ' . $bar;

Per me va bene se vuoi restituire 2-3 variabili, altrimenti dovresti usare un oggetto con le proprietà desiderate.


4

Ho implementato in questo modo per la funzione PHP valore di ritorno multiplo. sii gentile con il tuo codice. grazie.

 <?php
    function multi_retun($aa)
    {
        return array(1,3,$aa);
    }
    list($one,$two,$three)=multi_retun(55);
    echo $one;
    echo $two;
    echo $three;
    ?>

4

La risposta a cui è stato assegnato il segno di spunta verde sopra è effettivamente errata. Puoi restituire più valori in PHP, se restituisci un array. Vedi il seguente codice per un esempio:

<?php

function small_numbers()
{
    return array (0, 1, 2);
}

list ($zero, $one, $two) = small_numbers();

Questo codice è in realtà copiato dalla seguente pagina sul sito Web di PHP: http://php.net/manual/en/functions.returning-values.php Ho anche usato lo stesso tipo di codice molte volte, quindi posso confermare che è buono e funziona.


Tale risposta faceva riferimento all'esempio di codice nella domanda, quindi non è strettamente errata. Ma la domanda è ambigua. L'intenzione è probabilmente quella di restituire due valori da una chiamata di funzione.
Peter Mortensen,

3

Le funzioni in PHP possono restituire solo una variabile. potresti usare variabili con portata globale, puoi restituire array, oppure puoi passare variabili facendo riferimento alla funzione e poi cambiando valore, ma tutto ciò ridurrà la leggibilità del tuo codice. Suggerirei di esaminare le lezioni.


3

Ho pensato di espandere alcune delle risposte dall'alto ...

class nameCheck{

public $name;

public function __construct(){
    $this->name = $name;
}

function firstName(){
            // If a name has been entered..
    if(!empty($this->name)){
        $name = $this->name;
        $errflag = false;
                    // Return a array with both the name and errflag
        return array($name, $errflag);
            // If its empty..
    }else if(empty($this->name)){
        $errmsg = 'Please enter a name.';
        $errflag = true;
                    // Return both the Error message and Flag
        return array($errmsg, $errflag);
    }
}

}


if($_POST['submit']){

$a = new nameCheck;
$a->name = $_POST['name'];
//  Assign a list of variables from the firstName function
list($name, $err) = $a->firstName();

// Display the values..
echo 'Name: ' . $name;
echo 'Errflag: ' . $err;
}

?>
<form method="post" action="<?php $_SERVER['PHP_SELF']; ?>" >
<input name="name"  />
<input type="submit" name="submit" value="submit" />
</form>

Questo ti darà un campo di input e un pulsante di invio una volta inviato, se il campo di input del nome è vuoto restituirà il flag di errore e un messaggio. Se il campo nome ha un valore, restituirà il valore / nome e un flag di errore pari a 0 per false = nessun errore. Spero che questo ti aiuti!


3

Alcuni potrebbero preferire la restituzione di più valori come oggetto:

function test() {
    $object = new stdClass();

    $object->x = 'value 1';
    $object->y = 'value 2';

    return $object;
}

E chiamalo così:

echo test()->x;

O:

$test = test();
echo $test->y;

3

Sì e no. Non puoi restituire più di una variabile / oggetto, ma come suggerisci, puoi inserirli in un array e restituirlo.

Non c'è limite alla nidificazione di array, quindi puoi semplicemente impacchettarli in quel modo per tornare.


2

È sempre possibile restituire solo una variabile che potrebbe essere una matrice. Ma puoi modificare le variabili globali dall'interno della funzione. Questo è il più delle volte uno stile non molto buono, ma funziona. Nelle classi di solito si cambiano le variabili di classe all'interno delle funzioni senza restituirle.


1

La risposta è no. Quando il parser raggiunge la prima istruzione di ritorno, ricollegherà il controllo alla funzione chiamante - la tua seconda istruzione di ritorno non verrà mai eseguita.


A rigor di termini, sì. Ma la domanda è ambigua. Forse l'intento era di restituire due valori da una chiamata di funzione.
Peter Mortensen,

1

Aggiungi tutte le variabili in un array e infine restituisce il file array.

function test($testvar)
{
  // do something
  return array("var1" => $var1, "var2" => @var2);
}

E poi

$myTest = test($myTestVar);
//$myTest["var1"] and $myTest["var2"] will be usable

1

Penso che eliego abbia spiegato chiaramente la risposta. Ma se si desidera restituire entrambi i valori, inserirli in un array e restituirlo.

function test($testvar)
{
  // do something

  return array('var1'=>$var1,'var2'=>$var2);
//defining a key would be better some times   
}

// per accedere ai valori di ritorno

$returned_values = test($testvar);

echo $returned_values['var1'];
echo $returned_values['var2'];

Eri sobrio quando hai scritto questo? Posso individuare 2 errori a colpo d'occhio. 1) Usi la $thisparola chiave ma non è stata menzionata alcuna classe o oggetto. 2) Se hai restituito valori nella tua variabile $returned_values, dovresti echeggiare da quella variabile:echo $returned_values['var1'];
dading84

risolto il problema.
Gihan De Silva,

0
<?php
function foo(){
  $you = 5;
  $me = 10;
  return $you;
  return $me;
}

echo foo();
//output is just 5 alone so we cant get second one it only retuns first one so better go with array


function goo(){
  $you = 5;
  $me = 10;
  return $you_and_me =  array($you,$me);
}

var_dump(goo()); // var_dump result is array(2) { [0]=> int(5) [1]=> int(10) } i think thats fine enough

?>

0

Le lingue che consentono rendimenti multipli in genere convertono semplicemente i valori multipli in una struttura di dati.

Ad esempio, in Python è possibile restituire più valori. Tuttavia, in realtà vengono appena restituiti come una tupla.

Quindi puoi restituire più valori in PHP semplicemente creando un semplice array e restituendolo.


0

È possibile ottenere i valori di due o più variabili impostandole per riferimento:

function t(&$a, &$b) {
    $a = 1;
    $b = 2;
}


t($a, $b);

echo $a . '  ' . $b;

Produzione:

1 2

Ri "ottieni valori di due o più variabili" : Vuoi dire "restituisci valori di due o più variabili" ?
Peter Mortensen,

0

PHP utilizza ancora "parametri out"? In tal caso, è possibile utilizzare la sintassi per modificare uno o più parametri che entrano nella propria funzione. Saresti quindi libero di utilizzare la variabile modificata dopo il ritorno della funzione.


-1

Questo è il modo più semplice per farlo:

public function selectAllUsersByRole($userRole, $selector) {

    $this->userRole = $userLevel;
    $this->selector = $selector;

    $sql = "SELECT * FROM users WHERE role <= ? AND del_stat = 0";
    $stm = $this->connect()->prepare($sql); // Connect function in Dbh connect to database file
    $stm->execute([$this->userRole]); // This is PHP 7. Use array($this->userRole) for PHP 5

    $usersIdArray = array();
    $usersFNameArray = array();
    $usersLNameArray = array();

    if($stm->rowCount()) {
        while($row = $stm->fetch()) {

            array_push($usersIdArray,    $row['id']);
            array_push($usersFNameArray, $row['f_name']);
            array_push($usersLNameArray, $row['l_name']);

            // You can return only $row['id'] or f_name or ...
            // I used the array because it's most used.
        }
    }
    if($this->selector == 1) {
        return $usersIdArray;
    }elseif($this->selector == 2) {
        return $usersFNameArray;
    }elseif($this->selector == 3) {
        return $usersLNameArray;
    }

}

Come possiamo chiamare questa funzione?

$idData = $selectAllUsers->selectAllUsersByLevel($userRole, 0);
print_r($idData);
$idFName = $selectAllUsers->selectAllUsersByLevel($userRole, 1);
print_r($idFname);

Questo è tutto. Molto facile.


-1
$var1 = 0;
$var2 = 0;

function test($testvar, &$var1 , &$var2)
{
  $var1 = 1;
  $var2 = 2;
  return;
}
test("", $var1, $var2);

// var1 = 1, var2 = 2 

Non è un buon modo, ma penso che possiamo impostare due variabili in una funzione contemporaneamente.


-4

Ho avuto un problema simile - quindi ho provato e ho cercato su Google un po '(trovando questa discussione). Dopo 5 minuti di tentativi ed errori ho scoperto che puoi semplicemente usare "AND" per restituire due (forse più - non ancora testato) in una riga di ritorno.

Il mio codice:

  function get_id(){
    global $b_id, $f_id;
    // stuff happens
    return $b_id AND $f_id;
  }
  //later in the code:
  get_id();
  var_dump($b_id);
  var_dump($f_id); // tested output by var_dump

Funziona. Ho ottenuto entrambi i valori che mi aspettavo di ottenere / che avrei dovuto ottenere. Spero di poter aiutare chiunque legga questa discussione :)


3
Questo non è corretto 'AND' è semplicemente un operatore booleano, quindi la tua funzione sta effettivamente restituendo un singolo valore booleano. L'unico motivo per cui sembra funzionare è perché stai dichiarando $ b_id e $ f_id come variabili globali. Rimuovi "AND" e la dichiarazione di reso del tutto e vedrai che i tuoi risultati rimarranno gli stessi.
Matt Styles,

questo è molto fuorviante, dal momento che hai dichiarato $ b_id e $ f_id globali, quindi disponibili da qualsiasi contesto.
Paolo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.