Web

Множественные выходы из функции

Можно ли иметь функцию с двумя выходами следующим образом:

function test($testvar) {

  // некоторый код

  return $var1;

  return $var2;

}

Если да, то как я смогу получить каждый возврат отдельно?

 

Ответ 1

Не существует способа вернуть 2 переменные. Хотя вы можете использовать массив и вернуть его; создать условие для возврата динамической переменной и т. д. Например, эта функция вернет $var2:

function wtf($blahblah = true) {

    $var1 = "Один";

    $var2 = "Два";

    if($blahblah === true) {

      return $var2;

    }

    return $var1;

}

Применение:

echo wtf();

// вывод echo: Два

echo wtf("не true, но false");

// вывод echo: Один

 

Если вам нужны оба варианта, вы можете немного изменить функцию:

function wtf($blahblah = true) {

    $var1 = "Один";

    $var2 = "Два";

    if($blahblah === true) {

      return $var2;

    }

    if($blahblah == "both") {

      return array($var1, $var2);

    }

    return $var1;

}

 

echo wtf("both")[0]

// вывод echo: Один

echo wtf("both")[1]

// вывод echo: Два

list($first, $second) = wtf("both")

// значение $first будет $var1, значение $second будет $var2

 

Ответ 2

Технически вы не можете вернуть более одного значения. Однако существует множество способов обойти это ограничение. Наиболее похожим на возврат нескольких значений является способ с использованием ключевого слова list:

function getXYZ() {

    return array(4,5,6);

}

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

// После этого: $x == 4 && $y == 5 && $z == 6

// (Это будет справедливо для всех образцов, если не указано иное)

 

В итоге вы возвращаете массив и используете список для хранения элементов этого массива в различных значениях, вместо того чтобы хранить сам массив. Использование этой техники позволяет создать ощущение возврата нескольких значений. Решение с использованием списка является довольно специфическим для php. Есть несколько языков с похожими структурами, но еще больше языков, которые их не используют. Есть еще один способ, который обычно используется для «возврата» нескольких значений, и он доступен практически во всех языках (в том или ином виде). Однако этот способ выглядит совершенно иначе, поэтому к нему, возможно, придется привыкнуть:

// обратите внимание, что я назвал аргументы $a, $b и $c, чтобы показать.

// что им не нужно давать имена $x, $y и $z

function getXYZ(&$a, &$b, &$c) {

    $a = 4;

    $b = 5;

    $c = 6; 

}

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

 

Эта техника также используется в некоторых функциях, определенных самим php (например, $count в str_replace, $matches в preg_match). Это может показаться совершенно отличным от возврата нескольких значений, но об этом стоит хотя бы знать. Третий метод использовать объект для хранения различных нужных вам значений. Это более сложный способ, поэтому он используется не так часто, как два вышеописанных метода. Однако его использование может иметь смысл при использовании одного и того же набора переменных в нескольких местах (или, конечно, при работе на языке, который не поддерживает вышеупомянутые методы или позволяет сделать это без лишней типизации). 

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[0];

$y = $array[1];

$z = $array[2];

 

Самое интересное в приведенном выше коде заключается в том, что код внутри функции такой же, как и в самом первом примере, который я привел; изменился только код, вызывающий функцию. Это означает, что вызывающая функция сама решает, как относиться к результату, который возвращает функция. В качестве альтернативы можно использовать ассоциативный массив: 

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'];

 

Следует отметить, что у compact есть аналог extract, который можно было бы использовать в вызывающем коде, но так как это плохая идея использовать его (особенно для чего-то простого, как для вашего случая), я даже не буду приводить пример для него. Проблема в том, что он будет делать «магию» и создавать переменные за вас, в то время как вы не сможете увидеть, какие переменные создаются, не заходя в другие части кода. Наконец, я хотел бы упомянуть, что list не очень хорошо работает с ассоциативным массивом. Следующее действие сделает то, что вы ожидаете: Если вы использовали list с ассоциативным массивом, а в будущем кому-то другому придется изменить код в вызываемой функции (что может произойти практически в любой ситуации), он может внезапно сломаться, поэтому я бы не рекомендовал сочетать 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();

// Обратите внимание: $y == 6 && $z == 5

 

Ответ 3

Начиная с версии 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

 

Деструктуризация это очень мощный инструмент. Он также способен деструктурировать пары ключ => значение:

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

 

Ответ 4

Функции по определению возвращают только одно значение. Однако, как вы и предполагали, это значение может быть массивом. Поэтому вы, конечно, можете сделать что-то вроде:

<?PHP

function myfunc($a,$b){

   return array('foo'=>$a,'bar'=>$b);

}

print_r(myfunc('baz','bork'));

 

Тем не менее стоит задуматься над тем, что вы пытаетесь сделать. Хотя возврат сложного значения результата (например, массива или объекта) вполне допустим, если вы думаете о том, что «я хочу вернуть два значения», возможно, вы плохо проектируете свое приложение.

 

Схожие статьи

Web

Генератор случайных строк в PHP

Web

Принудительное использование SSL/https с помощью .htaccess и mod_rewrite

Web

Как преобразовать объект в массив

Web

Транзакции в PHP + MySQL