PHP Conference China 2020

返り値

オプションの return 文により値を返すことができます。 配列やオブジェクトを含むあらゆる型を返すことができます。 これにより、関数の実行を任意の箇所で終了し、その関数を呼び出した 箇所に制御を戻すことが出来ます。詳細に関しては return を参照してください。

注意:

return を省略した場合は NULL を返します。

return の使いかた

例1 return の使用法

<?php
function square($num)
{
    return 
$num $num;
}
echo 
square(4);   //  '16'を出力
?>

複数の値を返すことはできませんが、リストを返すことにより 同じ効果を得ることができます。

例2 複数の値を得るために配列を返す

<?php
function small_numbers()
{
    return array (
012);
}
list (
$zero$one$two) = small_numbers();
?>

関数からリファレンスを返すには、リファレンス演算子 & を関数宣 言部および変数への返り値を代入する際の両方で使用する必要があります。

例3 関数からリファレンスを返す

<?php
function &returns_reference()
{
    return 
$someref;
}

$newref =& returns_reference();
?>

リファレンスに関するさらに詳しい情報がリファレンスの説明にあります。

戻り値の型宣言

PHP 7 以降で、戻り値の型宣言が導入されました。 引数の型宣言 と同様に、戻り値の型宣言は、関数から戻される値の型を指定します。 戻り値の型宣言で使える は、引数の型宣言で使えるものと同じです。

厳密な型チェック は、戻り値の型宣言にも影響を及ぼします。デフォルトの弱い型付けでは、 もし戻り値の型が正しいものではなくても、自動的に型変換を行います。 この型変換が許されない場合 (たとえば、array を返す場合に、関数が integer を返している場合) は、 TypeError が発生します。 強い型付けの場合は、戻り値の型が正確に一致しなければならず、違っている場合は TypeError が発生します。

PHP 7.1.0 以降では、 返り値の型を void と宣言していない場合に引数がないreturn文を使うと、 E_COMPILE_ERROR が発生するようになりました。 これは、そのreturn文に到達しない場合であっても同じです。

PHP 7.1.0 以降では、型の名前の前にクエスチョンマーク (?) を付けることによって、 戻り値の値が nullable とマークできるようになりました。 これは、関数の戻り地の型が特定の型か、NULL を返すかの印になります。

注意:

親クラスのメソッドをオーバーライドする場合、子クラスのメソッドの戻り値の型は、 親クラスで宣言されたものと同じでなければいけません。 親クラスのメソッドが戻り値の型を宣言していない場合は、 子クラスのメソッドで型宣言をすることもできます。

例4 戻り値の型宣言の基本例

<?php
function sum($a$b): float {
    return 
$a $b;
}

// 戻り値が float となることに注目
var_dump(sum(12));
?>

上の例の出力は以下となります。

float(3)

例5 強い型付けの例

<?php
declare(strict_types=1);

function 
sum($a$b): int {
    return 
$a $b;
}

var_dump(sum(12));
var_dump(sum(12.5));
?>

上の例の出力は以下となります。

int(3)

Fatal error: Uncaught TypeError: Return value of sum() must be of the type integer, float returned in - on line 5 in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
  thrown in - on line 5

例6 オブジェクトを返す例

<?php
class {}

function 
getC(): {
    return new 
C;
}

var_dump(getC());
?>

上の例の出力は以下となります。

object(C)#1 (0) {
}

例7 Nullable な返り値の型宣言 (PHP 7.1.0 以降)

<?php
function get_item(): ?string {
    if (isset(
$_GET['item'])) {
        return 
$_GET['item'];
    } else {
        return 
null;
    }
}
?>
add a note add a note

User Contributed Notes 10 notes

up
32
ryan dot jentzsch at gmail dot com
3 years ago
PHP 7.1 allows for void and null return types by preceding the type declaration with a ? -- (e.g. function canReturnNullorString(): ?string)

However resource is not allowed as a return type:

<?php
function fileOpen(string $fileName, string $mode): resource
{
   
$handle = fopen($fileName, $mode);
    if (
$handle !== false)
    {
        return
$handle;
    }
}

$resourceHandle = fileOpen("myfile.txt", "r");
?>

Errors with:
Fatal error: Uncaught TypeError: Return value of fileOpen() must be an instance of resource, resource returned.
up
28
rstaveley at seseit dot com
10 years ago
Developers with a C background may expect pass by reference semantics for arrays. It may be surprising that  pass by value is used for arrays just like scalars. Objects are implicitly passed by reference.

<?php

# (1) Objects are always passed by reference and returned by reference

class Obj {
    public
$x;
}

function
obj_inc_x($obj) {
   
$obj->x++;
    return
$obj;
}

$obj = new Obj();
$obj->x = 1;

$obj2 = obj_inc_x($obj);
obj_inc_x($obj2);

print
$obj->x . ', ' . $obj2->x . "\n";

# (2) Scalars are not passed by reference or returned as such

function scalar_inc_x($x) {
   
$x++;
    return
$x;
}

$x = 1;

$x2 = scalar_inc_x($x);
scalar_inc_x($x2);

print
$x . ', ' . $x2 . "\n";

# (3) You have to force pass by reference and return by reference on scalars

function &scalar_ref_inc_x(&$x) {
   
$x++;
    return
$x;
}

$x = 1;

$x2 =& scalar_ref_inc_x($x);    # Need reference here as well as the function sig
scalar_ref_inc_x($x2);

print
$x . ', ' . $x2 . "\n";

# (4) Arrays use pass by value sematics just like scalars

function array_inc_x($array) {
   
$array{'x'}++;
    return
$array;
}

$array = array();
$array['x'] = 1;

$array2 = array_inc_x($array);
array_inc_x($array2);

print
$array['x'] . ', ' . $array2['x'] . "\n";

# (5) You have to force pass by reference and return by reference on arrays

function &array_ref_inc_x(&$array) {
   
$array{'x'}++;
    return
$array;
}

$array = array();
$array['x'] = 1;

$array2 =& array_ref_inc_x($array); # Need reference here as well as the function sig
array_ref_inc_x($array2);

print
$array['x'] . ', ' . $array2['x'] . "\n";
up
19
bgalloway at citycarshare dot org
12 years ago
Be careful about using "do this thing or die()" logic in your return lines.  It doesn't work as you'd expect:

<?php
function myfunc1() {
    return(
'thingy' or die('otherthingy'));
}
function
myfunc2() {
    return
'thingy' or die('otherthingy');
}
function
myfunc3() {
    return(
'thingy') or die('otherthingy');
}
function
myfunc4() {
    return
'thingy' or 'otherthingy';
}
function
myfunc5() {
   
$x = 'thingy' or 'otherthingy'; return $x;
}
echo
myfunc1(). "\n". myfunc2(). "\n". myfunc3(). "\n". myfunc4(). "\n". myfunc5(). "\n";
?>

Only myfunc5() returns 'thingy' - the rest return 1.
up
8
k-gun !! mail
3 years ago
With 7.1, these are possible yet;

<?php
function ret_void(): void {
   
// do something but no return any value
    // if needs to break fn exec for any reason simply write return;
   
if (...) {
        return;
// break
        // return null; // even this NO!
   
}

   
$db->doSomething();
   
// no need return call anymore
}

function
ret_nullable() ?int {
    if (...) {
        return
123;
    } else {
        return
null; // MUST!
   
}
}
?>
up
3
php(@)genjo(DOT)fr
11 months ago
Declaring a collection of objects as return type is not implemented and forbidden:
<?php
class Child{}

function
getChilds(): Child[]
{
    return [(new
Child()), (new Child())];
}

var_dump(getChilds());
// Returns:  Parse error: syntax error, unexpected '[', expecting '{'
?>

We have to use:
<?php
class Child{}

function
getChilds(): array
{
    return [(new
Child()), (new Child())];
}

var_dump(getChilds());
// Returns:
/*
array (size=2)
  0 =>
    object(Child)[168]
  1 =>
    object(Child)[398]
*/
?>

Idem for function parameter:
<?php
function setChilds(Child[] $childs){}
// Not allowed

function setChilds(array $childs){}
// Allowed
?>
up
3
Berniev
2 years ago
Be careful when introducing return types to your code.

Only one return type can be specified (but prefacing with ? allows null).

Return values of a type different to that specified are silently converted with sometimes perplexing results. These can be tedious to find and will need rewriting, along with calling code.

Declare strict types using "declare(strict_types=1);" and an error will be generated, saving much head-scratching.
up
3
zored dot box at gmail dot com
2 years ago
You may specify child return type if there is no parent:

<?php

class A {
    public function
f ($a)
    {
        return
1;
    }
}

class
B extends A {
    public function
f ($a): int // + return type, OK
   
{
        return
1;
    }
}

class
C extends A {
    public function
f (int $a) // + argument type, WARNING
   
{
        return
1;
    }
}
?>
up
9
nick at itomic.com
17 years ago
Functions which return references, may return a NULL value. This is inconsistent with the fact that function parameters passed by reference can't be passed as NULL (or in fact anything which isnt a variable).

i.e.

<?php

function &testRet()
{
    return
NULL;
}

if (
testRet() === NULL)
{
    echo
"NULL";
}
?>

parses fine and echoes NULL
up
3
ryan dot jentzsch at gmail dot com
5 years ago
PHP 7 return types if specified can not return a null.
For example:
<?php
declare(strict_types=1);

function
add2ints(int $x, int $y):int
{
   
$z = $x + $y;
    if (
$z===0)
    {
        return
null;
    }
    return
$z;
}
$a = add2ints(3, 4);
echo
is_null($a) ? 'Null' : $a;
$b = add2ints(-2, 2);
echo
is_null($b) ? 'Null' : $b;
exit();

Output:
7
Process finished with
exit code 139
up
0
Vidmantas Maskoliunas
4 years ago
Note: the function does not have "alternative syntax" as if/endif, while/endwhile, and colon (:) here is used to define returning type and not to mark where the block statement begins.
To Top