2

What would be the best way to check the type of an array in PHP?

Lets say I have the following:

class Toggler
{

    protected $devices;

    public function __construct(array $devices)
    {
        $this->devices = $devices;
    }

    public function toggleAll()
    {
        foreach ($this->devices as $device)
        {
            $device->toggle();
        }
    }

}

What happens here is simple: The Toggler class requires an array of 'Devices', loops over those devices and calls the toggle() method on them.

What I want however, is that the array of devices must contain only objects that implement the Toggleable interface (which would tell the object to supply a toggle() method).

Now I can't do something like this, right?

class Toggler
{

    protected $devices;

    public function __construct(Toggleable $devices)
    {
        $this->devices = $devices;
    }

    public function toggleAll()
    {
        foreach ($this->devices as $device)
        {
            $device->toggle();
        }
    }

}

As far as I know you can't typehint an array as an array in PHP has no type (unlike languages like C++).

Would you instead have to check type in the loop for each device? And throw an exception? What would be the best thing to do?

class Toggler
{

    protected $devices;

    public function __construct(array $devices)
    {
        $this->devices = $devices;
    }

    public function toggleAll()
    {
        foreach ($this->devices as $device)
        {
            if (! $device instanceof Toggleable) {
                throw new \Exception(get_class($device) . ' is not does implement the Toggleable interface.');
            }

            $device->toggle();
        }
    }

}

Is there a better, cleaner, way to do this? I figured as I was writing this pseudo code you would also need to check if the device is an object at all (else you can't do get_class($device)).

Any help would be appreciated.

3
  • stackoverflow.com/a/34273821/1848929 Commented Apr 13, 2017 at 18:29
  • It looks like you already found the solution. As an improvement I would do the instanceof validation when $this->devices is set (i.e. in the constructor) with two benefits: find any erroneous usage of class Toggler as soon as possible and make sure any object of the Toggler class is valid. Additional, a minor performance improvement: the constructor is called only once, another method may be called many times. Commented Apr 13, 2017 at 18:31
  • @hakiko Am I correct to say that toggleAll() would call a toggle(Toggler $toggler) for each item in the array? I love over-complicating problems lmao Commented Apr 13, 2017 at 18:33

1 Answer 1

5

One option (requires PHP >= 5.6.0) is to define the method as

public function __construct(Toggleable ...$devices)

but you'll have to use array packing/unpacking on both sides; the constructor and wherever you instantiate the object, e.g.

$toggleAbles = [new Toggleable(), new Toggleable()];
$toggler = new Toggler(...$toggleAbles);
Sign up to request clarification or add additional context in comments.

7 Comments

Damn that is smart, seems like the shortest and most elegant way of solving the issue. Do you think it's a better solution to the problem than: stackoverflow.com/questions/34273367/… ? What if later someone forgets to unpack the array of devices and inserts the entire array instead, would that be a problem?
If somebody forgot to unpack the array before instantiating the Toggler, then you'd get an array passed to the constructor which would be invalid as per the Toggleable typehint, and you'd get a recoverable fatal error or a TypeError Exception (depending on the version of PHP)
packed arguments must also be the last arguments in the function/constructor definition, which is another limitation
ah exactly! Thanks for the clarification
Would you agree with me that it would be a nice to have that you can strictly set the type of an array in PHP? That way, like in languages such as C++, you can only have values of a certain datatype in an array. That way you could just typehint the abstract directly, instead of unpacking an array using the splat operator.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.