関数からの複数の戻り


198

次のような2つの戻り値を持つ関数を持つことは可能ですか?

function test($testvar)
{
  // Do something

  return $var1;
  return $var2;
}

もしそうなら、どのように私は各リターンを別々に得ることができますか?


1
正確に何を達成しようとしていますか?きっとあなたが本当の問題を説明したなら、ここの誰かがあなたがエレガントな解決策にたどりつくのを手伝ってくれるでしょう。
マイクダニエルズ

3
質問では、2つの値のいずれか、または2つの値のいずれか、または2つの値の両方、または新しい概念の遅延評価を区別しません。1つ目は、あらゆる種類の条件付きフローで取るに足らないことです。2番目はpythonで許可されています:q、r = divmod(x、y); Lispと同様; PHPにはlist($ q、$ r)= twovals();が必要です。ハック、関数twovals(){return array($ a、$ b); }。遅延評価はかなり進んでおり、まだPHPに追いついていません。質問は正確ではないため、このエントリをこのトピックの明確な参照として使用しないことをお勧めします。
DragonLord

5
両方の値が必要な場合は、配列で返します。
Bhargav Nanekalva 2015年

2
PHP 7.1の@DragonLordでは、ショートリスト構文を
Janus Troelsen

1
重複する質問がありますが、より簡潔な回答を使用することで、ポイントまでの時間を短縮できます:関数から2つの値を返す
Gras Double

回答:


162

2つの変数を返す方法はありません。あなたは、が、することができます配列を伝播し、それを返します。動的変数などを返す条件を作成します。

たとえば、この関数は $var2

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

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

アプリケーション:

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

両方が必要な場合は、関数を少し変更できます

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
PHPだけにPerlがあった場合wantarray()
Marc B

6
ある条件に応じて、1つまたは異なる値を返す方法を説明する最初の部分を省略した場合、この回答は改善されます。この議論に参加する人々の99.999 +%が、両方の値を同時に返す方法を知りたいと確信しています。最高投票数の回答をご覧ください。
ToolmakerSteve

401

技術的には、複数の値を返すことはできません。ただし、その制限を回避する方法は複数あります。複数の値を返すように最も機能する方法は、listキーワードを使用することです。

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)

技術的には、配列を返し、listその配列の要素を実際の配列を格納する代わりに別の値で格納するために使用しています。このテクニックを使用すると最も複数の値を返すように。

list解決策ではなくPHP固有のものです。同様の構造を持ついくつかの言語がありますが、そうでない言語はさらに多くあります。複数の値を「返す」ために一般的に使用される別の方法があり、ほぼすべての言語で(何らかの方法で)使用できます。ただし、この方法は外観がまったく異なるため、慣れる必要がある場合があります。

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

この技術はまた、(例えば、PHP自体によって定義されたいくつかの機能に使用される$countstr_replace$matchesするpreg_match)。これは、複数の値を返すこととはかなり異なるように感じるかもしれませんが、少なくとも知っておく価値はあります。

3番目の方法は、オブジェクトを使用して、必要なさまざまな値を保持することです。これはタイピングが多いため、上記の2つの方法ほど頻繁には使用されません。ただし、同じ変数セットを複数の場所で使用する場合(または、もちろん、上記のメソッドをサポートしていないか、追加の入力なしでこれを実行できる言語で作業している場合)は、これを使用するのが理にかなっています。

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;

上記のメソッドは、関数から複数の値を返す主な方法をまとめたものです。ただし、これらの方法にはバリエーションがあります。注目すべき最も興味深いバリエーションは、実際には配列を返すものです。これは、PHPで配列を使用して実行できることがたくさんあるためです。

まず、単純に配列を返し、それを配列以外のものとして扱うことはできません。

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

$array = getXYZ();

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

上記のコードで最も興味深い部分は、関数内のコードが、最初に提供した最初の例と同じであることです。関数を呼び出すコードのみが変更されました。つまり、関数が返す結果をどのように処理するかは、関数を呼び出す側次第です。

あるいは、連想配列を使用することもできます。

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

$array = getXYZ();

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

Phpにはcompact、上記と同じことを行うことができますが、より少ないコードを記述できる関数があります。(まあ、サンプルのコードは減りませんが、実際のアプリケーションはおそらくそうでしょう。)しかし、タイピングの節約量は最小限であり、コードを読みにくくするので、私はそれを自分ではしません。それにもかかわらず、ここにサンプルがあります:

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

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

$array = getXYZ();

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

注意すべきことはcompactextractここで、呼び出し元のコードで使用することができることを、それは(特にこのような単純な何かのために)それを使用することは悪い考えだので、私もそれ用のサンプルを与えることはありません。問題は、「マジック」を実行して変数を作成する一方で、コードの他の部分に移動しないとどの変数が作成されるかを確認できないことです。

最後に、私が言及したいと思いますlistしない、本当に連想配列とよく遊びます。以下はあなたが期待することをします:

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

$array = getXYZ();

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

ただし、以下は別のことを行います。

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

$array = getXYZ();

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

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

list連想配列を使用していて、他の誰かが呼び出された関数のコードを将来変更する必要がある場合(これはあらゆる状況で発生する可能性があります)、突然壊れる可能性があるためlist、連想配列と組み合わせることはお勧めしません。


2
また:return compact( 'var1'、 'var2'、 'var3');
bjudson 2010

1
これは別のオプションですが、配列を返すのと同じように、複数の値を返すようには感じません。それは私だけかもしれません。個人的には私はもっとreturn array('x' => $x, 'y' => $y, 'z' => $z)きれいだと思いますが、自分で書こうと思うほどではなく、他の人にその形式を使用するよう依頼するほどではありません。
Jasper

2
List()を使用することは、私が経験した類似の問題に対する素晴らしい答えです。これは、複数の変数を検証して関数に戻す優れた方法です。php docsをざっと見てみると、この関数にさらに光が当てられ、おそらくより明確になります。php.net/manual/en/function.list.php .. Jasperに感謝!
JustinP 2012年

2
+1は、そのような広範な回答、特にそのような幅広い一般的な質問に対する回答です。それにもかかわらず、この答えは私に非常に役立ちました。
Lee Blake

2
@Mikey歴史的な理由。この回答は元々、別の質問に投稿されていましたが、この質問と完全に重複しているため削除されました(実際には古い質問でしたが)。回答は、この質問をした人の最後の訪問より後にこの質問に移動されました。
ジャスパー2017年

73

あなたの例では、2番目の戻りは決して起こりません-最初の戻りはPHPが実行する最後のものです。複数の値を返す必要がある場合は、配列を返します。

function test($testvar) {

    return array($var1, $var2);
}

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

18
あなたも行うことができます:list($result_1, result_2) = test($testvar);
ティム・クーパー

@ティム・クーパー:result_2または$result_2
Peter Mortensen

@PeterMortensen:$result_2
Tim Cooper、

46

PHP 7.1以降、リストの適切な分解が行われています。これにより、次のようなことができます。

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

関数では、これは次のようになります。

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

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

破壊は非常に強力なツールです。key => valueのペアも分解できます:

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

PHP 7.1の新機能ページをご覧ください。

新機能


5
StackOverflowが質問の作成時に受け入れられなかった場合でも、StackOverflowが「注目の回答」のような機能を持っているといいのですが、この回答は非常に役立ち、更新されていますが、もちろんトピックから外れています。
Jonatas CD

3
@JonatasCD-この回答が「オフトピック」であるとあなたが言う理由がわかりません。PHP 7.1では、それはある関数から複数の戻り値を作成して処理するための最も便利な方法。したがって、新しいphpバージョンでは、元の受け入れられた回答よりも優れた回答になります。
ToolmakerSteve

@ToolmakerSteve誤解されていると思います。質問に対する「主題外」は、将来の実装に基づいて、受け入れられた質問を変更できるようにするという私の提案でした。それはあなたの答えに反するものではありませんでした;)
Jonatas CD 19/04/10

@JonatasCD-それを説明するああ。(私の答えではありません、私は戸惑いました。)少なくとも「これは受け入れられた答えよりも最新です」というタグおそらく3人がそのタグに同意する必要があり、それが注目されるようになります。:)
ToolmakerSteve

26

PHP 5.5には、新しい概念もあります。つまりgenerators、関数から複数の値を生成できます。

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

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

16

または、参照渡しすることもできます。

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

$a = 0;
$b = 0;

byRef(10, $a, $b);

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

これは出力します

100
1000

9

私はかなり遅れていることを知っていますが、この問題には素晴らしくシンプルな解決策があります。
構造化を使用して、一度に複数の値を返すことが可能です。

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

これを使用できます

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

extract配列内の各メンバーの変数を作成し、そのメンバーにちなんで名前を付けます。したがって、これでアクセス$modelして$data


1
注:キー(ここmodeldata)が変数としてまだ存在していないことに注意してください。存在する場合は、prefixパラメータを使用してextract競合を回避します。
ToolmakerSteve

7

関数から複数の配列とスカラーを返すことができます

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

2つのreturnステートメントを持つことはできません。ただし、エラーはスローされませんが、関数が呼び出されると、最初のreturnステートメント値のみが返されます。return of arrayを使用して、複数の値を返すことができます。例えば:

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

関数は、定義により、1つの値のみを返します。

ただし、想定したとおり、その値は配列にすることができます。

だからあなたは確かに次のようなことをすることができます:

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

とはいえ、少し時間をかけて、解決しようとしていることについて考えることは価値があります。複雑な結果値(配列やオブジェクトなど)を返すことは完全に有効ですが、「2つの値を返したい」と考えている場合は、設計が不十分である可能性があります。あなたの質問に詳細がなければ、言うのは難しいですが、立ち止まって二度考えることは決して害にはなりません。


5

ベストプラクティスは、返された変数を配列に入れてlist()から、配列値を変数に割り当てることです。

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

はい、オブジェクトを使用できます:-)

しかし、最も簡単な方法は配列を返すことです:

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

5

PHP 7.1 <=の場合、(list関数の代わりに)新しい構文を使用できます。

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

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

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

2〜3個の変数を返したい場合は私にとっては問題ありません。それ以外の場合は、目的のプロパティを持つオブジェクトを使用する必要があります。


4

複数の戻り値のPHP関数にこのように実装しました。あなたのコードをうまく使ってください。ありがとうございました。

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

4

上記の緑色のチェックマークを付けた答えは実際には正しくありません。配列を返す場合、PHPで複数の値を返すことができます。例については、次のコードを参照してください。

<?php

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

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

このコードは、実際にPHPのウェブサイト上で、次のページからコピーされます。http://php.net/manual/en/functions.returning-values.php 私はまた、自身がコードの同じ種類を何度も使ってきたので、ということを確認することができますそれは良いことであり、うまくいくことです。


その回答は質問のコード例を参照しているため、厳密に間違っているわけではありません。しかし、質問があいまいです。その目的は、おそらく1つの関数呼び出しから2つの値を返すことです
Peter Mortensen

3

PHPの関数は1つの変数のみを返すことができます。グローバルスコープで変数を使用したり、配列を返したり、関数を参照して変数を渡したり、値を変更したりできますが、コードの読みやすさが低下します。クラスを調べることをお勧めします。


3

上記の回答のいくつかを詳しく説明すると思います。

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>

これにより、入力フィールドと送信ボタンが送信されます。名前入力フィールドが空の場合は、エラーフラグとメッセージが返されます。名前フィールドに値がある場合、値/名前と、false =エラーなしのエラーフラグ0を返します。お役に立てれば!


3

オブジェクトとして複数の値を返すことを好む人もいます。

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

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

    return $object;
}

次のように呼び出します。

echo test()->x;

または:

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

3

はいといいえ。複数の変数/オブジェクトを返すことはできませんが、提案したように、それらを配列に入れて返すことができます。

配列のネストに制限はないので、それらをそのままパッケージ化して返すことができます。


2

常に配列である可能性のある変数を1つだけ返すことができます。ただし、関数内からグローバル変数を変更できます。それはほとんどの場合、あまり良いスタイルではありませんが、うまくいきます。クラスでは、通常、関数内からクラス変数を変更せずに変更します。


1

答えはいいえだ。パーサーが最初のreturnステートメントに到達すると、呼び出し元の関数に制御が戻されます。2番目のreturnステートメントは実行されません。


厳密に言えば、はい。しかし、質問があいまいです。おそらく、1つの関数呼び出しから2つの値を返すことが目的でした。
Peter Mortensen

1

すべての変数を配列に追加し、最後にを返しますarray

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

その後

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

1

eliegoが答えを明確に説明したと思います。ただし、両方の値を返したい場合は、それらを配列に入れて返します。

function test($testvar)
{
  // do something

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

//戻り値にアクセスする

$returned_values = test($testvar);

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

これを書いたとき、あなたは冷静でしたか?私は一目で2つの間違いを見つけることができます。1)$thisキーワードを使用しているが、言及されているクラスまたはオブジェクトがない。2)あなたは変数に値を戻した場合$returned_values、あなたはその変数からエコーする必要がありますecho $returned_values['var1'];
dading84

問題を修正しました。
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

複数の戻りを許可する言語は、通常、複数の値をデータ構造に変換するだけです。

たとえば、Pythonでは複数の値を返すことができます。ただし、実際には1つのタプルとして返されます。

したがって、単純な配列を作成してそれを返すだけで、PHPで複数の値を返すことができます。


0

参照で設定することにより、2つ以上の変数の値を取得できます。

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


t($a, $b);

echo $a . '  ' . $b;

出力:

1 2

「は、2つの以上の変数の値を取得する」:あなたが意味するか「は、2つの以上の変数の戻り値を」
Peter Mortensen

0

PHPはまだ「出力パラメータ」を使用していますか?その場合は、構文を使用して、関数に渡される1つ以上のパラメーターを変更できます。関数が戻った後は、変更した変数を自由に使用できます。


-1

これが最も簡単な方法です。

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

}

この関数をどのように呼び出すことができますか?

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

それでおしまい。非常に簡単。


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

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

// var1 = 1, var2 = 2 

これは良い方法ではありませんが、関数に2つの変数を同時に設定できると思います。


-4

私も同様の問題を抱えていました-そこで私はいろいろ試してググった(このスレッドを見つけた)。5分間試行錯誤した結果、「AND」を使用すると、1行で2つ(多分-まだテストされていません)を返すことができることがわかりました。

私のコード:

  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

できます。取得する/取得するはずの両方の値を取得しました。私はこのスレッドを読んでいる誰かを助けることができれば幸いです:)


3
これは正しくありません。「AND」は単なるブール演算子であるため、関数は実際には単一のブール値を返します。$ b_idと$ f_idをグローバル変数として宣言しているため、機能すると思われます。「AND」とreturnステートメントを完全に削除すると、結果が同じままであることがわかります。
Matt Styles

$ b_idと$ f_idをグローバルに宣言したので、これは非常に誤解を招きやすいため、どのコンテキストからでも使用できます。
paulus 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.