Is it possible to specify more than one type hint for a parameter?
Solution 1
That is not possible to enforce (except inside the method). You can only provide a single type hint, and only to objects/interfaces and arrays (since PHP 5.1).
You can/should however document it in your method, i.e:
/**
* @param string|Bar|Baz $param1
*/
function foo($param1);
Solution 2
This is one use of interfaces. If you want to be sure that the object has a ->foobar($baz)
method, you could expect an interface:
interface iFooBar {
public function foobar($baz);
}
class Foo implements iFooBar {
public function foobar($baz) { echo $baz; }
}
class Bar implements iFooBar {
public function foobar($baz) { print_r($baz); }
}
function doSomething(iFooBar $foo) {
$foo->foobar('something');
}
Then, when calling, these will work:
doSomething(new Foo());
doSomething(new Bar());
These will not:
doSomething(new StdClass());
doSomething('testing');
Solution 3
At the time of this writing there is no support for multiple explicit types. You have to rely on documentation and PHP's dynamic type system.
However, I do have a mostly incomplete proposal for union types. It is targeting 7.NEXT (at the time of this writing this is 7.1) or 8 (whichever comes first).
Here is a simple example of something that I think would be very valuable: array | Traversable
:
function map(callable $fn, array|Traversable $input) {
foreach ($input as $key => $value) {
yield $key => $fn($value);
}
}
Unfortunately the RFC did not pass; however for the specific type array|Traversable
there is now an iterable
type which is exactly that.
Solution 4
Fantastic question. It applies to both IDE documentation and PHP 5 Type Hinting. You have to remember that in OO polymorphism is your friend.
If you create a base class and extend them, your type hint will be base class... all extended class will work. See example below.
//
$test = new DUITest();
// Calls below will work because of polymorphism
echo $test->test(new Molecule()) . '<br/>';
echo $test->test(new Vodka()) . '<br/>';
echo $test->test(new Driver()) . '<br/>';
echo $test->test(new Car()) . '<br/>';
// Will not work because different data type
echo $test->test(new Pig()) . '<br/>';
echo $test->test(new Cop()) . '<br/>';
echo $test->test('test') . '<br/>';
echo $test->test(array()) . '<br/>';
/**
* Class to test
*/
class DUITest {
public function __construct() {
;
}
/**
* Using type-hinting
*
* See below link for more information
* @link http://www.php.net/manual/en/language.oop5.typehinting.php
*
* @param Molecule|Car|Driver|Vodka $obj
*/
public function test(Molecule $obj) {
echo $obj;
}
}
/**
* Base Class
*/
class Molecule {
public function __construct() {}
/**
* Outputs name of class of current object
* @return <type>
*/
public function __toString() {
return get_class($this);
}
}
class Car extends Molecule {}
class Driver extends Molecule {}
class Vodka extends Molecule {}
class Pig {}
class Cop extends Pig{}
Solution 5
Type hinting only allows for one hint per parameter (and also, the hint needs to be array
or a class name, you can't hint string
), but you can do this by checking the type of the param within your function, using get_class
:
function foo($param)
{
if (!(is_string($param) || in_array(get_class($param), array("Bar", "Baz")))
{
// invalid type for $param!
}
}
You could even use trigger_error
to have it fail with a PHP error (like it would if a type hint failed) if you wanted.
joao
Updated on June 06, 2022Comments
-
joao about 2 years
Is there a way to add more than one type hinting to a method? For example, foo(param) must receive a instance of string OR bar OR baz.
-
ircmaxell over 13 yearsI'd suggest throwing a
InvalidArgumentException
, so that you can at least attempt to recover from the error... -
Bruce over 13 years@ircmaxell I was just demonstrating how the OP could replicate how type hints work.
-
joao over 13 yearsPretty cool! There are SPL types too (experimental): pl.php.net/manual/en/book.spl-types.php
-
ircmaxell over 13 yearsI'm not saying not to
trigger_error
. It all depends on your style (and there's nothing wrong with usingtrigger_error
). I prefer exceptions, so I useInvalidArgumentException
. If your goal is to mimic type hints, then by all means trigger a fatal error... -
Bruce over 13 years@ircmaxell Agreed; I personally wouldn't use
trigger_error
for this either :) -
ircmaxell over 13 years@joao: SPLTypes won't work on 5.3 (They use deprecated c calls). Plus the last update was in 2008, so it's pretty safe to say it's not current...
-
chris342423 almost 8 yearsUpdate: Since PHP 7 string (and bool, int, float) is a valid type hint.
-
faintsignal over 6 yearsUpdate: PHP 7.1 added nullable hint types and PHP 7.2 adds the object hint type.
-
Victor Bredihin over 5 yearscool, but what's about null? It's a usual practice to return something or null
-
Dharman over 5 yearsYour proposal has been rejected. Is there any future plan for this in PHP8?
-
Levi Morrison over 5 yearsNot that I know of. I think it's worth pursuing, but personally I will be working on other features.