Vários retornos de uma função

198

É possível ter uma função com dois retornos como este:

function test($testvar)
{
  // Do something

  return $var1;
  return $var2;
}

Se sim, como eu seria capaz de obter cada retorno separadamente?

vincent
fonte
1
O que exatamente você está tentando realizar? Certamente, se você explicou seu problema real, alguém aqui pode ajudá-lo a encontrar uma solução elegante.
Mike Daniels
3
A pergunta não diferencia entre um / dois dos dois valores, dois dos dois valores ou a avaliação preguiçosa do novo conceito um e possivelmente dois dos dois valores. O primeiro é trivial com qualquer tipo de fluxo condicional. O segundo é permitido em python: q, r = divmod (x, y); assim como Lisp; PHP requer a lista ($ q, $ r) = twovals (); hack, onde a função twovals () {retorna array ($ a, $ b); } A avaliação preguiçosa é bastante avançada e ainda não pegou o PHP. Como a pergunta não é precisa, recomendamos não usar esta entrada como referência definitiva para este tópico.
precisa saber é o seguinte
5
Se você precisar dos dois valores, retorne-os em uma matriz.
Bhargav Nanekalva
2
@DragonLord no PHP 7.1, você pode usar a lista curta sintaxe
Janus Troelsen
1
Há uma pergunta duplicada, mas com respostas mais concisas, assim, você será mais rápido ao ponto: Retornando 2 valores de uma função .
Gras Double

Respostas:

162

Não há como retornar 2 variáveis. Embora você possa propagar uma matriz e retorná-la; crie um condicional para retornar uma variável dinâmica etc.

Por exemplo, essa função retornaria $var2

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

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

Na aplicação:

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

Se você quisesse os dois, poderia modificar um pouco a função

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
fonte
15
Se apenas PHP teve de Perlwantarray()
Marc B
6
IMHO esta resposta seria melhorada se omitir a primeira parte, que discute como retornar um ou um valor diferente, dependendo de alguma condição. Estou certo de que 99,999 +% das pessoas que participam dessa discussão querem saber como retornar os dois valores ao mesmo tempo. Veja a resposta mais votada.
Home
401

Tecnicamente, você não pode retornar mais de um valor. No entanto, existem várias maneiras de contornar essa limitação. A maneira que funciona mais como retornar vários valores é com a listpalavra-chave:

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, você está retornando uma matriz e usando listpara armazenar os elementos dessa matriz em valores diferentes, em vez de armazenar a matriz real. O uso dessa técnica fará com que pareça mais com o retorno de vários valores.

A listsolução é bastante específica para php. Existem alguns idiomas com estruturas semelhantes, mas outros não. Existe outra maneira que é comumente usada para "retornar" vários valores e está disponível em praticamente todos os idiomas (de uma maneira ou de outra). No entanto, esse método terá uma aparência bem diferente, portanto, pode ser necessário se acostumar.

// 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 também é usada em algumas funções definidas pelo próprio php (por exemplo, $countem str_replace , $matchesem preg_match ). Isso pode parecer bem diferente do retorno de vários valores, mas vale a pena conhecer pelo menos.

Um terceiro método é usar um objeto para armazenar os diferentes valores necessários. Como é mais digitado, não é usado com tanta frequência quanto os dois métodos acima. Pode fazer sentido usar isso, porém, ao usar o mesmo conjunto de variáveis ​​em vários locais (ou, é claro, trabalhar em um idioma que não suporta os métodos acima ou permite que você faça isso sem digitar mais).

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;

Os métodos acima resumem as principais maneiras de retornar vários valores de uma função. No entanto, existem variações nesses métodos. As variações mais interessantes a serem observadas são aquelas nas quais você realmente está retornando uma matriz, simplesmente porque há muito que você pode fazer com matrizes em PHP.

Primeiro, podemos simplesmente retornar uma matriz e não tratá-la como algo além de uma matriz:

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

$array = getXYZ();

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

A parte mais interessante sobre o código acima é que o código dentro da função é o mesmo que no primeiro exemplo que forneci; somente o código que chama a função foi alterado. Isso significa que cabe a quem chama a função como tratar o resultado que a função retorna.

Como alternativa, pode-se usar uma matriz associativa:

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

$array = getXYZ();

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

Php tem a compactfunção que permite fazer o mesmo que o descrito acima, mas enquanto escreve menos código. (Bem, o exemplo não terá menos código, mas provavelmente um aplicativo do mundo real.) No entanto, acho que a quantidade de economia de digitação é mínima e torna o código mais difícil de ler, então eu não faria isso sozinho. No entanto, aqui está uma amostra:

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

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

$array = getXYZ();

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

Note-se que, embora compacttenha uma contrapartida emextract poderia ser usado no código de chamada aqui, mas como é uma má idéia usá-lo (especialmente para algo tão simples como este), nem mesmo darei uma amostra. O problema é que ele fará "mágica" e criará variáveis ​​para você, enquanto você não pode ver quais variáveis ​​são criadas sem ir para outras partes do código.

Finalmente, gostaria de mencionar que realmentelist não funciona bem com o array associativo. O seguinte fará o que você espera:

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

$array = getXYZ();

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

No entanto, o seguinte fará 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

Se você usou listcom uma matriz associativa e alguém tiver que alterar o código na função chamada no futuro (o que pode acontecer em qualquer situação), ela poderá se romper repentinamente, por isso eu recomendaria não combinar listcom matrizes associativas.

Jaspe
fonte
2
Também: return compact ('var1', 'var2', 'var3');
precisa saber é o seguinte
1
Essa é outra opção, mas não me parece retornar vários valores, como retornar uma matriz. Isso pode ser apenas eu embora. Pessoalmente, eu acharia return array('x' => $x, 'y' => $y, 'z' => $z)mais limpo, mas até o ponto em que eu mesmo o escreveria, e não no ponto em que pediria que outros usassem esse formato.
Jasper
2
Usar List () é uma ótima resposta para um problema semelhante que tive. essa é uma excelente maneira de validar e retornar várias variáveis ​​de volta para uma função. uma rápida olhada nos documentos do php irá esclarecer mais essa função e, talvez, torná-la mais clara. php.net/manual/en/function.list.php .. obrigado Jasper!
19412 JustinP
2
+1 para uma resposta tão extensa, especialmente para uma pergunta tão ampla e geral. Apesar disso, esta resposta me ajudou imensamente.
Lee Blake
2
@Mikey Razões históricas. Esta resposta foi originalmente postada em uma pergunta diferente, que foi excluída por ser uma duplicata exata desta (apesar do fato de ser realmente mais antiga). A resposta foi movida para esta pergunta depois da última visita de quem fez essa pergunta.
Jasper
73

No seu exemplo, o segundo retorno nunca acontecerá - o primeiro retorno é a última coisa que o PHP executará. Se você precisar retornar vários valores, retorne uma matriz:

function test($testvar) {

    return array($var1, $var2);
}

$result = test($testvar);
echo $result[0]; // $var1
echo $result[1]; // $var2
Fonte de Tim
fonte
18
Você também pode fazer:list($result_1, result_2) = test($testvar);
Tim Cooper
@ Tim Cooper: result_2ou $result_2?
Peter Mortensen
@PeterMortensen:$result_2
Tim Cooper
46

Desde o PHP 7.1, temos a destruição adequada das listas. Dessa forma, você pode fazer coisas assim:

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

Em uma função, seria assim:

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

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

A reestruturação é uma ferramenta muito poderosa. Também é capaz de desestruturar pares chave => valor:

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

Dê uma olhada na nova página de recursos do PHP 7.1:

Novas características

Nukesor
fonte
5
Eu gostaria que o StackOverflow tivesse um recurso como 'resposta em destaque' mesmo quando não for aceito no momento da criação da pergunta, porque essa resposta aqui é bastante útil e atualizada, mas é fora de tópico, é claro.
Jonatas CD
3
@ JonatasCD - não sei por que você diz que esta resposta é "fora do tópico". No php 7.1, é a maneira mais conveniente de criar e manipular vários valores de retorno de uma função. Portanto, para versões mais recentes de php, é uma resposta superior à resposta aceita original.
Home
@ToolmakerSteve Eu acho que você me entendeu mal. "fora do tópico" da pergunta foi minha sugestão de poder alterar o que era a pergunta aceita com base em implementações futuras. Não foi nada contra a sua resposta;)
Jonatas CD 04/04
@ JonatasCD - Ahh, isso explica. (Não é minha resposta, fiquei perplexo.) Pelo menos uma tag que diz "isso é mais atualizado do que a resposta aceita". Talvez três pessoas tenham que concordar com essa tag e ela se destaque. :)
ToolmakerSteve
26

No PHP 5.5, há também um novo conceito:, generatorsonde você pode gerar vários valores a partir de uma função:

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

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

Ou você pode passar por referência:

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

$a = 0;
$b = 0;

byRef(10, $a, $b);

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

Isso produziria

100
1000
Jake N
fonte
9

Sei que estou muito atrasado, mas existe uma solução simples e agradável para esse problema.
É possível retornar vários valores ao mesmo tempo usando a desestruturação.

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

Agora você pode usar isso

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

extractcria uma variável para cada membro da matriz, nomeada após esse membro. Agora você pode acessar $modele$data

Muhammad Raheel
fonte
1
NOTA: tenha cuidado para que as chaves (aqui modele data) ainda não existam como variáveis. Se o fizerem, use o prefixparâmetro de extractpara evitar conflitos.
Home
7

Você pode retornar várias matrizes e escalares de uma função

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
fonte
7

Não é possível ter duas declarações de retorno. No entanto, ele não gera erro, mas quando a função é chamada, você receberá apenas o primeiro valor da instrução de retorno. Podemos usar o retorno da matriz para obter vários valores em troca. Por exemplo:

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
fonte
5

As funções, por definição, retornam apenas um valor.

No entanto, como você supôs, esse valor pode ser uma matriz.

Então você certamente pode fazer algo como:

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

Dito isto, vale a pena tomar um momento e pensar sobre o que você está tentando resolver. Embora o retorno de um valor de resultado complexo (como uma matriz ou um objeto) seja perfeitamente válido, se você pensa que "eu quero retornar dois valores", você pode estar com um design ruim. Sem mais detalhes na sua pergunta, é difícil dizer, mas nunca é demais parar e pensar duas vezes.

timdev
fonte
5

A melhor prática é colocar as variáveis ​​retornadas na matriz e, em seguida, usar list()para atribuir valores de matriz às variáveis.

<?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
fonte
5

Sim, você pode usar um objeto :-)

Mas a maneira mais simples é retornar uma matriz:

return array('value1', 'value2', 'value3', '...');
Rufinus
fonte
5

Para o PHP 7.1 <= você pode usar a nova sintaxe (em vez da função list ):

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

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

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

Tudo bem para mim se você deseja retornar 2-3 variáveis, caso contrário, você deve usar um objeto com as propriedades desejadas.

Marek Gralikowski
fonte
4

Eu implementei assim para a função PHP com vários valores de retorno. seja legal com seu código. obrigado.

 <?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
fonte
4

A resposta que recebeu o visto verde acima está incorreta. Você pode retornar vários valores no PHP, se retornar uma matriz. Veja o código a seguir para um exemplo:

<?php

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

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

Na verdade, esse código é copiado da página a seguir no site do PHP: http://php.net/manual/en/functions.returning-values.php Também usei o mesmo tipo de código muitas vezes, para confirmar que é bom e funciona.

craig-c
fonte
Essa resposta se refere ao exemplo de código na pergunta, portanto, não é estritamente incorreta. Mas a questão é ambígua. A intenção é provavelmente retornar dois valores de uma chamada de função.
Peter Mortensen
3

Funções no PHP podem retornar apenas uma variável. você pode usar variáveis ​​com escopo global, retornar uma matriz ou passar uma variável por referência à função e alterar o valor, mas tudo isso diminuirá a legibilidade do seu código. Eu sugeriria que você olhasse para as aulas.

dobrisa.com
fonte
3

Pensei em expandir algumas das respostas de cima ....

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>

Isso fornecerá um campo de entrada e um botão de envio, uma vez enviado, se o campo de entrada do nome estiver vazio, ele retornará o sinalizador de erro e uma mensagem. Se o campo de nome tiver um valor, ele retornará o valor / nome e um sinalizador de erro 0 para false = sem erros. Espero que isto ajude!

Kyle Coots
fonte
3

Alguns podem preferir retornar vários valores como objeto:

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

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

    return $object;
}

E chame assim:

echo test()->x;

Ou:

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

Sim e não. Você não pode retornar mais de uma variável / objeto, mas como sugere, você pode colocá-los em uma matriz e retornar isso.

Não há limite para o aninhamento de matrizes, então você pode empacotá-las dessa maneira para retornar.

Rick
fonte
2

Você sempre pode retornar apenas uma variável que pode ser uma matriz. Mas você pode alterar variáveis ​​globais de dentro da função. Na maioria das vezes, esse estilo não é muito bom, mas funciona. Nas aulas, você geralmente altera as variáveis ​​de classe de dentro das funções sem retorná-las.

2ndkauboy
fonte
1

A resposta é não. Quando o analisador alcança a primeira instrução de retorno, ele direcionará o controle de volta para a função de chamada - sua segunda instrução de retorno nunca será executada.

eliego
fonte
Estritamente falando, sim. Mas a questão é ambígua. Talvez a intenção fosse retornar dois valores de uma chamada de função.
Peter Mortensen
1

Adicione todas as variáveis ​​em uma matriz e, finalmente, retorne o array.

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

E depois

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

Acho que eliego explicou a resposta claramente. Mas se você quiser retornar os dois valores, coloque-os em uma matriz e retorne-os.

function test($testvar)
{
  // do something

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

// para acessar valores de retorno

$returned_values = test($testvar);

echo $returned_values['var1'];
echo $returned_values['var2'];
Gihan De Silva
fonte
Você estava sóbrio quando escreveu isso? Eu consigo identificar 2 erros de relance. 1) Você usa a $thispalavra - chave, mas não há classe ou objeto mencionado. 2) Se você retornou valores em sua variável $returned_values, então você deve ecoar a partir dessa variável:echo $returned_values['var1'];
dading84
corrigiu o 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
fonte
0

Idiomas que permitem retornos múltiplos geralmente convertem os valores múltiplos em uma estrutura de dados.

Por exemplo, em Python, você pode retornar vários valores. No entanto, eles realmente estão sendo retornados como uma tupla.

Assim, você pode retornar vários valores no PHP criando apenas uma matriz simples e retornando isso.

plaina
fonte
0

Você pode obter os valores de duas ou mais variáveis, definindo-as por referência:

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


t($a, $b);

echo $a . '  ' . $b;

Resultado:

1 2
Jacek Wysocki
fonte
Re "obter valores de duas ou mais variáveis" : Você quer dizer "retornar valores de duas ou mais variáveis" ?
Peter Mortensen
0

O PHP ainda usa "parâmetros fora"? Nesse caso, você pode usar a sintaxe para modificar um ou mais dos parâmetros que entram na sua função. Você seria livre para usar a variável modificada após o retorno da sua função.

Camião35
fonte
-1

Esta é a maneira mais fácil de fazer isso:

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

}

Como podemos chamar essa função?

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

É isso aí. Muito fácil.

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

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

// var1 = 1, var2 = 2 

Não é uma boa maneira, mas acho que podemos definir duas variáveis ​​em uma função ao mesmo tempo.

khanhkid
fonte
-4

Eu tive um problema semelhante - então tentei e pesquisei um pouco (encontrando este tópico). Após 5 minutos de tentativa e erro, descobri que você pode simplesmente usar "AND" para retornar dois (talvez mais - ainda não testados) em uma linha de retorno.

Meu 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. Eu obtive os dois valores que esperava obter / deveria obter. Espero poder ajudar alguém a ler este tópico :)

Stefan
fonte
3
Isso não está correto. 'AND' é simplesmente um operador booleano, portanto, sua função está realmente retornando um único valor booleano. A única razão pela qual parece funcionar é porque você está declarando $ b_id e $ f_id como variáveis ​​globais. Remova completamente a declaração 'AND' e a declaração de retorno e você verá que seus resultados permanecem os mesmos.
Styles Matt
isso é muito enganador, pois você declarou $ b_id e $ f_id global, portanto disponíveis em qualquer contexto.
paulus 01/07