- Php multiple return types
- Использование выражения return
- User Contributed Notes 10 notes
- How to Specify Multiple Return Types on PHP 7
- Is it possible to specify multiple return types on PHP 7?
- PHP 7: Multiple function return types
- Multiple returns from a function
- What type hint to use if return value is mixed?
- Is it possible to type hint more than one type?
- Union types in PHP
- Workarounds
- The day PHP (almost) had union types
- PHP class method return type
Php multiple return types
Значения возвращаются при помощи необязательного оператора возврата. Возвращаемые значения могут быть любого типа, в том числе это могут быть массивы и объекты. Возврат приводит к завершению выполнения функции и передаче управления обратно к той строке кода, в которой данная функция была вызвана. Для получения более детальной информации ознакомьтесь с описанием return .
Замечание:
Если конструкция return не указана, то функция вернёт значение null .
Использование выражения return
Пример #1 Использование конструкции return
Функция не может возвращать несколько значений, но аналогичного результата можно добиться, возвращая массив.
Пример #2 Возврат нескольких значений в виде массива
function small_numbers ()
return [ 0 , 1 , 2 ];
>
// Деструктуризация массива будет собирать каждый элемент массива индивидуально
[ $zero , $one , $two ] = small_numbers ();
?php
// До версии 7.1.0 единственной эквивалентной альтернативой было использование конструкции list().
list( $zero , $one , $two ) = small_numbers ();
Для того, чтобы функция возвращала результат по ссылке, вам необходимо использовать оператор & и при описании функции, и при присвоении переменной возвращаемого значения:
Пример #3 Возврат результата по ссылке
Для получения более детальной информации о ссылках обратитесь к разделу документации Подробно о ссылках.
User Contributed Notes 10 notes
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:
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.
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.
# (1) Objects are always passed by reference and returned by reference
function obj_inc_x ( $obj ) $obj -> x ++;
return $obj ;
>
$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 ;
>
$x2 = scalar_inc_x ( $x );
scalar_inc_x ( $x2 );
# (3) You have to force pass by reference and return by reference on scalars
$x2 =& scalar_ref_inc_x ( $x ); # Need reference here as well as the function sig
scalar_ref_inc_x ( $x2 );
# (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
$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» ;
Be careful about using «do this thing or die()» logic in your return lines. It doesn’t work as you’d expect:
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.
With 7.1, these are possible yet;
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!
>
>
?>
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).
if ( testRet () === NULL )
echo «NULL» ;
>
?>
parses fine and echoes NULL
PHP 7 return types if specified can not return a null.
For example:
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
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.
You may specify child return type if there is no parent:
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 ;
>
>
?>
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.
Declaring a collection of objects as return type is not implemented and forbidden:
class Child <>
function getChilds (): Child [] return [(new Child ()), (new Child ())];
>
var_dump ( getChilds ());
// Returns: Parse error: syntax error, unexpected ‘[‘, expecting ‘ ?>
We have to use:
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:
function setChilds ( Child [] $childs )<>
// Not allowed
function setChilds (array $childs )<>
// Allowed
?>
How to Specify Multiple Return Types on PHP 7
Is it possible to specify multiple return types on PHP 7?
As of PHP 8+, you may use union types:
function test(): FailObject|SuccessObject <>
Another way, available in all versions since PHP 4, is for the two objects to share an interface. Example:
interface ReturnInterface <>
class FailObject implements ReturnInterface <>
class SuccessObject implements ReturnInterface <>
function test(): ReturnInterface <>
In this example, ReturnInterface is empty. Its mere presence supports the needed return type declaration.
You could also use a base, possibly abstract, class.
To me, for this use case, interfaces are more clear and more extensible than union types. For example, if I later want a WarnObject I need only to define it as extending ReturnInterface — rather than going through all signatures and updating them to FailObject|SuccessObject|WarnObject .
PHP 7: Multiple function return types
Updating this as of 2020.
There has been vote for Union types and it was accepted to PHP 8.
https://wiki.php.net/rfc/union_types_v2
To have multiple return types in PHP you just need to have PHP 8, otherwise it is simply not possible at all. However, you should not be dumm and set everything as possible return, as it might make your code a mess. @Adam Cameron explains this very well in his answer.
Multiple returns from a function
There is no way of returning 2 variables. Although, you can propagate an array and return it; create a conditional to return a dynamic variable, etc.
For instance, this function would return $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
If you wanted them both, you could modify the function a bit
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
What type hint to use if return value is mixed?
Type hints are there to enforce some restriction on the value passed or returned. Since «mixed» would allow any value at all, its use as a type hint would be pointless, so just omit it.
From PHP 8.0 onwards, you can specify «union types», which would allow you to declare the return type in your example as bool|string . (There is also a special case for including false in the union, as in false|string , since it’s commonly used to indicate failure, but not for true .)
As an alternative to false|string you can use nullable type hints, which are available from PHP 7.1 onwards. , and can be specified as ?string if you want to return null on a failure instead of false .
In older versions, you can document the return value of your function, in a docblock. IDEs and documentation generators will generally understand the syntax @return bool|string . Even if you are using PHP 8, you might want to use this to add a description of why the return type varies, and when to expect which type.
Of course, an option well worth considering is to reconsider your design, and come up with a function which can communicate its result without returning different types for different cases. For instance, using exceptions instead of a special value for errors, or splitting a function like getThing(boolean $asString): float|string into two functions getThingAsFloat(): float and getThingAsString(): string .
Is it possible to type hint more than one type?
Academically, this is called a type union.
Union types in PHP
You can cheat by creating interfaces, parent types, etc, as mentioned in other answers, but what’s the point, apart for adding complexity and LoCs to your project? Plus, that can’t work for scalar types as you can’t extend/implement a scalar type.
Instead of making the code more readable, you’ll get the opposite. Except if those classes/interfaces already existed and they are here because of OOP, not to solve a type hinting problem.
Workarounds
The canonical answer in PHP is. well, just don’t put a type hint. The language was not thought to have a complex and powerful type system, and trying to workaround the flaws of the language is not a good answer.
Instead, document your function properly:
/**
* Description of what the function does.
*
* @param User|File $multiTypeArgument Description of the argument.
*
* @return string[] Description of the function’s return value.
*/
function myFunction($multiTypeArgument)
This will at least bring IDE support for autocompletion and static code analysis. Well enough when working on a private project, website, etc.
When designing a public API (a PHP library, etc), sometimes you may want to be more defensive about API consumers’ inputs.
Then @tilz0R answer is the way to go:
function log($message) if (!is_string($message) && !$message instanceof Message) throw new \InvalidArgumentException('$message must be a string or a Message object.');
>
// code .
>
The day PHP (almost) had union types
The 14th of February 2015, the Union Types PHP RFC was proposed for PHP 7.1. After discussion and vote, it’s been rejected, 18 «no» against 11 «yes».
If the RFC had been accepted, PHP would have had union types exactly the way you’ve shown ( User|File ).
The RFC had some flaws, but the main reason for why it’s been rejected is that the mainteners voters are quite resistive to change especially when it’s about type strictness and other programming paradigms (ex. «why would we need type unions when the default takes all types of values» and «that’s not good for performance»).
PHP class method return type
As per this page :
http://php.net/manual/en/language.types.type-juggling.php
Now PHP offer return type declaration from PHP 7. I have explained how to use return type in PHP