views:

784

answers:

3

In PHP it is possible to specify argument types although they call it type hinting.

I am implementing an interface where one of the functions specifies an array as the argument type:

function myFunction(array $argument){
}

I'd like to define a class, an instance of which can be used as the argument for this function. In other words it would extend ArrayObject or implement ArrayAccess or something along those lines.

Is there a built in interface or abstract class that will work for this? (ArrayObject doesn't)

+2  A: 

There isn't, but I'd suggest two alternatives:

  1. Remove the array specifier and rather check within the function using is_array and instanceof ArrayObject
  2. Use (array) $ArrayObject when calling the routine or as part of 1. above.

Example for soulmerge :-)

function myFunction(array $argument){
    echo var_export($argument,true);
}
$a = new ArrayObject();
$a[] = 'hello';
$a[] = 'and goodbye';

myFunction((array)$a);

outputs

 array (
   0 => 'hello',
   1 => 'and goodbye',
 )
Just Jules
Note that the second option will convert your object into an array mapping the member names of the object to their values, it will not make you use of the ArrayObject functions!
soulmerge
Since the interface is not defined by me I don't have the option of dropping the type hint.I think option 2 will serve my purpose best as I want to have more control over the keys and values than I get from using a regular array.So I will use my own object and cast it to array when I pass it to the function.
Adrian Hope-Bailie
Note $a[]= and $a->append() are equivalent as ArrayObject implements arrayaccess. At some point php.net will document their libraries.
Just Jules
+2  A: 

This isn't possible. array() is not an object of any class. Hence, it can't implement any interface (see here). So you can't use an object and an array interchangeably. The solution strongly depends on what you'd like to achieve.

Why don't you change the function signature to allow only ArrayObjects, ArrayIterators, ArrayAccesss, IteratorAggregates, Iterators or Traversables (depending on what you'd like to do inside the function)?

If you have to rely on interation-capabilities of the passed object you should use Traversable as the type-hint. This will ensure that the object can be used with foreach(). If you need array-like key-access to the object (e.g. $test['test']) you should use ArrayAccess as the type-hint. But if you need the passed object to be of a specific custom type, use the custom type as the type-hint.

Another option would be to not use a type-hint at all and determine the type of the passed argument within the function body and process the argument accordingly (or throw an InvalidArgumentException or something like that).

if (is_array($arg)) { ... }
else if ($arg instanceof Traversable) { ... }
else if ($arg instanceof ArrayAccess) { ... }
else {
    throw new InvalidArgumentException('...');
}
Stefan Gehrig
A: 

No, this is not possible, as array is a primitive type in PHP. An instance of a class is an object, and the PHP-internal comparison already stops at this point (Interfaces and the like are not checked).

You could create an array out of your object:

$array = array();
foreach ($yourObject as $key => $value) {
    $array[$key] = $value;
}
soulmerge