简体   繁体   中英

PHP Type Hinting: array supported, object NOT?

Am I missing something or there really is no support for generic object type hinting in PHP 5.x?

I find it really strange that hinting arrays is supported while hinting objects is not, at least not out of the box.

I'd like to have something like this:

function foo(object $o)

Just as we have:

function foo(array $o)

Example of possible use: methods of an objects collection class.

Workaround: using an interface "Object" implemented by all classes or extending all classes from a generic class "Object" and writing something like this:

function foo(Object $o)

Well, that just ain't cute.

Using stdClass as the type hint doesn't work:

Catchable fatal error: Argument 1 passed to c::add() must be an instance of stdClass, instance of b given

Since type hinting should make the client code adapt to your API, your solution with accepting interfaces seems just about right.

Look at it this way: yourMethod(array $input) gives yourMethod() an array to use, thereby you know exactly which native functions that applies and can be used by yourMethod() .

If you specify your method like: yourSecondMethod(yourInterface $input) you'd also know which methods that can be applied to $input since you know about/can lookup which set of rules that accompanies the interface yourInterface .

In your case, accepting any object seems wrong, because you don't have any way of knowing which methods to use on the input. Example:

function foo(Object $o) {
    return $o->thisMethodMayOrMayNotExist();
}

(Not implying that syntax is valid)

No, it can't be done. I wasn't missing anything.

I feel your pain, but I can't find a way of doing it either.

Despite what a number of other posters have said, it makes perfect sense to want 'Object' type hinting; they just haven't considered a scenario that requires it.

I am trying to do some work with the reflection API, and because of that I don't care what class is passed to my function. All I care is that it's an object. I don't want an int, a float, a string or an array. I want an object. Given that reflection is now part of PHP, it definitely makes sense to have object type hinting.

You cannot just say "object" when type casting an object... you must define WHICH object you are expecting.

From: http://php.net/manual/en/language.oop5.typehinting.php

class MyClass
{
    /**
     * A test function
     *
     * First parameter must be an object of type OtherClass
     */
    public function test(OtherClass $otherclass) {
        echo $otherclass->var;
    }


    /**
     * Another test function
     *
     * First parameter must be an array
     */
    public function test_array(array $input_array) {
        print_r($input_array);
    }
}

// Another example class
class OtherClass {
    public $var = 'Hello World';
}

The best way to enforce this would be to create a degenerate interface called Object . A degenerate interface means it has no defined methods.

interface Object {

   // leave blank

}

Then in your base classes, you can implement Object .

class SomeBase implements Object {

   // your implementation

}

You can now call your function as you wanted to

function myFunc (Object $obj);

myFunc($someBase);

If you pass any object which inherits from your Object interface, this type hint will pass. If you pass in an array, int, string etc, the type hint will fail.

Here's another example where it is required...

I've created a class to implement record locking. Records being one of a number of different object types. The locking class has several methods which require an object (the one to be locked) but don't care what type of object it is.

Eg

public static function lockRecord($record, User $user, $timeout=null)
{
    if(!is_object($record)) throw new \InvalidException("Argument 1 must be an object.");

    $lock=new Lock();
    $lock->setRecord($record);
    $lock->setUser($user);
    $lock->setTimeout($timeout);
    $lock->activate();
    return($lock);
}

You'll see that my solution was to use is_object() and throw an exception, but I'd far rather be able to do it with type hinting instead.

Ok, so not the end of the world, but I think it's a shame.

Objects in php are not subclasses of some StdClass or Object as it is in other OOP languages. So there is no way of type hinting the object. But I see your point because sometimes you want to make sure that the Object is being passed, so I guess the only way is to raise the issue manually.

public function yourFunction($object){
    if(is_object($object)){
        //TODO: do something
    }else{
        throw new InvalidArgumentException;
    }
}

As of php 5.4 there is also a type hint callable . See php manual http://php.net/manual/en/language.types.callable.php

public static function cloneObject($source)
{
    if ($source === null)
    {
        return null;
    }

    return unserialize(serialize($source));
}

This is where you would need it.

Why would you want to hint object when you can hint an actual class name instead - this would be much more useful. Also remember that you can't hint int , float , bool , string or resource either.

Since PHP 7.2 you can finally declare the way you wanted:

function functionName(object $someObjectVariable)

See the table named "Valid types" at this page: https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM