Retornos múltiples de una función

198

¿Es posible tener una función con dos retornos como este:

function test($testvar)
{
  // Do something

  return $var1;
  return $var2;
}

Si es así, ¿cómo podría obtener cada devolución por separado?

vincent
fuente
1
¿Qué es exactamente lo que estás tratando de lograr? Seguramente si explicaste tu problema real, alguien aquí podría ayudarte a llegar a una solución elegante.
Mike Daniels
3
La pregunta no distingue entre uno o dos de los dos valores, ambos dos de dos valores, o un nuevo concepto de evaluación diferida de uno y posiblemente dos de dos valores. El primero es trivial con cualquier tipo de flujo condicional. El segundo está permitido en python: q, r = divmod (x, y); así como Lisp; PHP requiere la lista ($ q, $ r) = twovals (); hack, donde function twovals () {return array ($ a, $ b); }. La evaluación diferida es bastante avanzada y aún no se ha implementado en PHP. Como la pregunta no es precisa, recomiende no utilizar esta entrada como referencia definitiva para este tema.
DragonLord
55
Si necesita ambos valores, devuélvalos en una matriz.
Bhargav Nanekalva
2
@DragonLord en PHP 7.1, puede usar la sintaxis de la lista corta
Janus Troelsen
1
Hay una pregunta duplicada, pero con respuestas más concisas, lo que lo llevará más rápido al punto: devolver 2 valores de una función .
Gras Double

Respuestas:

162

No hay forma de devolver 2 variables. Sin embargo , puede propagar una matriz y devolverla; crear un condicional para devolver una variable dinámica, etc.

Por ejemplo, esta función devolvería $var2

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

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

En aplicación:

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

Si los quisieras a ambos, podrías modificar un poco la función

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
dockeryZ
fuente
15
Si solo PHP tuviera Perl'swantarray()
Marc B
66
En mi humilde opinión, esta respuesta mejoraría si omitiera la primera parte, que analiza cómo devolver uno o un valor diferente, dependiendo de alguna condición. Estoy seguro de que el 99.999 +% de las personas que vienen a esta discusión quieren saber cómo devolver ambos valores al mismo tiempo. Ver la respuesta más votada.
ToolmakerSteve
401

Técnicamente, no puede devolver más de un valor. Sin embargo, hay varias formas de evitar esa limitación. La forma en que actúa más como devolver múltiples valores es con la listpalabra clave:

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)

Técnicamente, está devolviendo una matriz y utilizando listpara almacenar los elementos de esa matriz en diferentes valores en lugar de almacenar la matriz real. El uso de esta técnica hará que parezca más como devolver múltiples valores.

La listsolución es bastante específica de php. Hay algunos idiomas con estructuras similares, pero hay más idiomas que no. Hay otra forma que se usa comúnmente para "devolver" múltiples valores y está disponible en casi todos los idiomas (de una forma u otra). Sin embargo, este método se verá bastante diferente, por lo que es posible que necesite acostumbrarse.

// 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);

Esta técnica también se usa en algunas funciones definidas por el propio php (por ejemplo, $counten str_replace , $matchesen preg_match ). Esto puede parecer bastante diferente de devolver múltiples valores, pero vale la pena al menos saberlo.

Un tercer método es usar un objeto para contener los diferentes valores que necesita. Esto es más mecanografía, por lo que no se usa con tanta frecuencia como los dos métodos anteriores. Sin embargo, puede tener sentido usar esto cuando se usa el mismo conjunto de variables en varios lugares (o, por supuesto, trabajar en un lenguaje que no admite los métodos anteriores o le permite hacer esto sin escribir más).

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;

Los métodos anteriores resumen las principales formas de devolver múltiples valores de una función. Sin embargo, hay variaciones en estos métodos. Las variaciones más interesantes a tener en cuenta son aquellas en las que realmente está devolviendo una matriz, simplemente porque hay mucho que puede hacer con las matrices en PHP.

Primero, simplemente podemos devolver una matriz y no tratarla como algo más que una matriz:

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

$array = getXYZ();

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

La parte más interesante sobre el código anterior es que el código dentro de la función es el mismo que en el primer ejemplo que proporcioné; solo cambió el código que llama a la función. Esto significa que depende de quien llama a la función cómo tratar el resultado que devuelve la función.

Alternativamente, uno podría usar una matriz asociativa:

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

$array = getXYZ();

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

Php tiene la compactfunción que le permite hacer lo mismo que antes pero al escribir menos código. (Bueno, la muestra no tendrá menos código, pero una aplicación del mundo real probablemente sí.) Sin embargo, creo que la cantidad de ahorro de escritura es mínima y hace que el código sea más difícil de leer, por lo que no lo haría yo mismo. Sin embargo, aquí hay una muestra:

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

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

$array = getXYZ();

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

Cabe señalar que si bien compacttiene una contraparte extractque podría usarse en el código de llamada aquí, pero dado que es una mala idea usarlo (especialmente para algo tan simple como esto), ni siquiera daré una muestra. El problema es que hará "magia" y creará variables para usted, mientras que no puede ver qué variables se crean sin ir a otras partes del código.

Finalmente, me gustaría mencionar que realmentelist no funciona bien con la matriz asociativa. Lo siguiente hará lo que espera:

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

$array = getXYZ();

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

Sin embargo, lo siguiente hará algo diferente:

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

$array = getXYZ();

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

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

Si lo usó listcon una matriz asociativa, y alguien más tiene que cambiar el código en la función llamada en el futuro (lo que puede suceder en cualquier situación) puede romperse repentinamente, por lo que recomendaría no combinarlo listcon matrices asociativas.

Jaspe
fuente
2
También: return compact ('var1', 'var2', 'var3');
bjudson
1
Esa es otra opción, pero no me parece que devuelva varios valores, al igual que devolver una matriz. Eso puede ser solo yo sin embargo. Personalmente, encontraría return array('x' => $x, 'y' => $y, 'z' => $z)más limpio, pero hasta el punto en que lo escribiría yo mismo, no hasta el punto en que pediría a otros que usen ese formato.
Jasper
2
Usar List () es una gran respuesta a un problema simular que tuve. Esta es una excelente manera de validar y devolver múltiples variables de nuevo a una función. un vistazo rápido a los documentos php arrojará más luz sobre esta función y quizás lo aclare más. php.net/manual/en/function.list.php .. ¡gracias Jasper!
JustinP
2
+1 para una respuesta tan extensa, especialmente a una pregunta tan amplia y general. A pesar de eso, esta respuesta me ha ayudado inmensamente.
Lee Blake
2
@Mikey Razones históricas. Esta respuesta se publicó originalmente en una pregunta diferente, que se eliminó por ser un duplicado exacto de esta (a pesar de que en realidad era más antigua). La respuesta se trasladó a esta pregunta más tarde que la última visita de quien hizo esta pregunta.
Jasper
73

En su ejemplo, el segundo retorno nunca sucederá: el primer retorno es lo último que ejecutará PHP. Si necesita devolver múltiples valores, devuelva una matriz:

function test($testvar) {

    return array($var1, $var2);
}

$result = test($testvar);
echo $result[0]; // $var1
echo $result[1]; // $var2
Fuente de tim
fuente
18
También puedes hacer:list($result_1, result_2) = test($testvar);
Tim Cooper
@Tim Cooper: result_2o $result_2?
Peter Mortensen
@PeterMortensen:$result_2
Tim Cooper
46

Desde PHP 7.1 tenemos la desestructuración adecuada para las listas. De este modo puedes hacer cosas como esta:

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

En una función, esto se vería así:

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

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

La desestructuración es una herramienta muy poderosa. También es capaz de desestructurar pares clave => valor:

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

Eche un vistazo a la nueva página de características para PHP 7.1:

Nuevas características

Nukesor
fuente
55
Desearía que StackOverflow tuviera una característica como 'respuesta destacada' incluso cuando no es aceptada en el momento de la creación de la pregunta porque esta respuesta aquí es bastante útil y actualizada, pero está fuera de tema, por supuesto.
Jonatas CD
3
@JonatasCD: no estoy seguro de por qué dice que esta respuesta está "fuera de tema". En php 7.1 es la forma más conveniente de crear y manejar múltiples valores de retorno de una función. Entonces, para las nuevas versiones de php, es una respuesta superior a la respuesta original aceptada.
ToolmakerSteve
@ToolmakerSteve Creo que me entendiste mal. "fuera de tema" a la pregunta fue mi sugerencia de poder cambiar cuál fue la pregunta aceptada en base a implementaciones futuras. No fue nada en contra de su respuesta;)
CD de Jonatas
@JonatasCD - Ahh, eso lo explica. (No es mi respuesta, estaba perplejo). Al menos una etiqueta que dice "esto está más actualizado que la respuesta aceptada" Quizás tres personas tengan que estar de acuerdo con esa etiqueta, y luego aparece. :)
ToolmakerSteve
26

En PHP 5.5 también hay un nuevo concepto: generatorsdonde puede obtener múltiples valores de una función:

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

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

O puede pasar por referencia:

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

$a = 0;
$b = 0;

byRef(10, $a, $b);

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

Esto daría salida

100
1000
Jake N
fuente
9

Sé que llego bastante tarde, pero hay una solución simple y agradable para este problema.
Es posible devolver múltiples valores a la vez utilizando la desestructuración.

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

Ahora puedes usar esto

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

extractcrea una variable para cada miembro de la matriz, con el nombre de ese miembro. Por lo tanto, ahora puede acceder $modely$data

Muhammad Raheel
fuente
1
NOTA: tenga cuidado de que las claves (aquí modely data) no existan como variables. Si lo hacen, use el prefixparámetro de extractpara evitar conflictos.
ToolmakerSteve
7

Puede devolver múltiples matrices y escalares desde una función

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);
zzapper
fuente
7

No es posible tener dos declaraciones de devolución. Sin embargo, no arroja error, pero cuando se llama a la función, solo recibirá el primer valor de declaración de retorno. Podemos usar return of array para obtener múltiples valores a cambio. Por ejemplo:

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);
}
Apsar
fuente
5

Las funciones, por definición, solo devuelven un valor.

Sin embargo, como supuso, ese valor puede ser una matriz.

Entonces ciertamente puedes hacer algo como:

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

Dicho esto, vale la pena tomarse un momento y pensar en lo que sea que esté tratando de resolver. Si bien devolver un valor de resultado complejo (como una matriz o un objeto) es perfectamente válido, si piensa que "Quiero devolver dos valores", es posible que esté diseñando mal. Sin más detalles en su pregunta, es difícil de decir, pero nunca está de más detenerse y pensar dos veces.

timdev
fuente
5

La mejor práctica es colocar las variables devueltas en una matriz y luego usarlas list()para asignar valores de matriz a las variables.

<?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 />';

?>
Wael Assaf
fuente
5

Sí, puedes usar un objeto :-)

Pero la forma más simple es devolver una matriz:

return array('value1', 'value2', 'value3', '...');
Rufino
fuente
5

Para PHP 7.1 <= puede usar una nueva sintaxis (en lugar de la función de lista ):

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

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

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

Está bien para mí si desea devolver 2-3 variables, de lo contrario, debe usar un objeto con las propiedades deseadas.

Marek Gralikowski
fuente
4

He implementado así para la función PHP de valor de retorno múltiple. Sé amable con tu código. gracias.

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

La respuesta que se le da al tick verde anterior es realmente incorrecta. Puede devolver múltiples valores en PHP, si devuelve una matriz. Consulte el siguiente código para ver un ejemplo:

<?php

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

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

Este código se copia de la siguiente página en el sitio web de PHP: http://php.net/manual/en/functions.returning-values.php También he usado el mismo tipo de código muchas veces, así que puedo confirmar que es bueno y que funciona

craig-c
fuente
Esa respuesta se refería al ejemplo de código en la pregunta, por lo que no es estrictamente incorrecta. Pero la pregunta es ambigua. La intención es probablemente devolver dos valores de una llamada de función.
Peter Mortensen
3

Las funciones en PHP solo pueden devolver una variable. puede usar variables con alcance global, puede devolver una matriz o puede pasar variables por referencia a la función y luego cambiar el valor, pero todo eso disminuirá la legibilidad de su código. Te sugiero que estudies las clases.

dobrisa.com
fuente
3

Pensé que ampliaría algunas de las respuestas de arriba ...

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>

Esto le dará un campo de entrada y un botón de envío una vez enviado, si el campo de entrada de nombre está vacío, devolverá el indicador de error y un mensaje. Si el campo de nombre tiene un valor, devolverá el valor / nombre y un indicador de error de 0 para falso = sin errores. ¡Espero que esto ayude!

Kyle Coots
fuente
3

Algunos podrían preferir devolver múltiples valores como objeto:

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

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

    return $object;
}

Y llámalo así:

echo test()->x;

O:

$test = test();
echo $test->y;
hovado
fuente
3

Si y no. No puede devolver más de una variable / objeto, pero como sugiere, puede ponerlos en una matriz y devolverlos.

No hay límite para la anidación de matrices, por lo que puede empaquetarlas de esa manera para regresar.

Almiar
fuente
2

Siempre puede devolver solo una variable que podría ser una matriz. Pero puede cambiar las variables globales desde dentro de la función. La mayoría de las veces no es un estilo muy bueno, pero funciona. En las clases, generalmente se cambian las variables de clase desde las funciones sin devolverlas.

2ndkauboy
fuente
1

La respuesta es no. Cuando el analizador llega a la primera declaración de retorno, dirigirá el control nuevamente a la función de llamada; su segunda declaración de retorno nunca se ejecutará.

eliego
fuente
Estrictamente hablando, sí. Pero la pregunta es ambigua. Quizás la intención era devolver dos valores de una llamada de función.
Peter Mortensen
1

Agregue todas las variables en una matriz y finalmente devuelva el array.

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

Y entonces

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

Creo que eliego ha explicado la respuesta claramente. Pero si desea devolver ambos valores, colóquelos en una matriz y devuélvalos.

function test($testvar)
{
  // do something

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

// para acceder a los valores de retorno

$returned_values = test($testvar);

echo $returned_values['var1'];
echo $returned_values['var2'];
Gihan De Silva
fuente
¿Estabas sobrio cuando escribiste esto? Puedo detectar 2 errores de un vistazo. 1) Utiliza la $thispalabra clave pero no se menciona ninguna clase u objeto. 2) Si devolvió valores a su variable $returned_values, entonces debería hacer eco de esa variable:echo $returned_values['var1'];
dading84
solucionó el 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

?>
Liakat
fuente
0

Los lenguajes que permiten retornos múltiples generalmente solo convierten los valores múltiples en una estructura de datos.

Por ejemplo, en Python puede devolver múltiples valores. Sin embargo, en realidad solo se devuelven como una tupla.

Por lo tanto, puede devolver múltiples valores en PHP simplemente creando una matriz simple y devolviéndola.

tplaner
fuente
0

Puede obtener los valores de dos o más variables configurándolas por referencia:

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


t($a, $b);

echo $a . '  ' . $b;

Salida:

1 2
Jacek Wysocki
fuente
Re "obtener valores de dos o más variables" : ¿Quiere decir "valores de retorno de dos o más variables" ?
Peter Mortensen
0

¿PHP todavía usa "parámetros de salida"? Si es así, puede usar la sintaxis para modificar uno o más de los parámetros que entran en su función. Entonces sería libre de usar la variable modificada después de que regrese su función.

Camión35
fuente
-1

Esta es la forma más fácil de hacerlo:

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;
    }

}

¿Cómo podemos llamar a esta función?

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

Eso es. Muy fácil.

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

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

// var1 = 1, var2 = 2 

No es una buena manera, pero creo que podemos establecer dos variables en una función al mismo tiempo.

khanhkid
fuente
-4

Tuve un problema similar, así que probé y busqué en Google un poco (encontrar este hilo). Después de 5 minutos de prueba y error, descubrí que simplemente puede usar "Y" para devolver dos (tal vez más, aún no probado) en una línea de retorno.

Mi código:

  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

funciona. Obtuve los dos valores que esperaba obtener / debería obtener. Espero poder ayudar a cualquiera que lea este hilo :)

Stefan
fuente
3
Esto no es correcto. 'AND' es simplemente un operador booleano, por lo que su función en realidad está devolviendo un único valor booleano. La única razón por la que parece funcionar es porque está declarando $ b_id y $ f_id como variables globales. Elimine el 'AND' y la declaración de devolución por completo y verá que sus resultados siguen siendo los mismos.
Matt Styles
esto es muy engañoso, ya que declaró $ b_id y $ f_id global, por lo tanto, está disponible desde cualquier contexto.
paulus