Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I check if a variable is "loopable"?

Tags:

php

I got a method that receives a parameter that could be any number of types.

It could be an array.

It could be an object that is in some way iterable such as a collection.

It could be something else altogether such as a string or integer which would throw

Warning: Invalid argument supplied for foreach()

How can I reliably check that the variable is "loopable" to avoid the warning?

I've tried is_array() as below but that only works for arrays:

if(is_array($mystery_type)){
    foreach($mystery_type as $value){
        ...
    }
}

I was surprised to not find an answer to this here, which probably means it's very simple and I'm missing something obvious.

like image 958
Bananaapple Avatar asked Oct 20 '25 10:10

Bananaapple


2 Answers

If you are using PHP 7.1+ you can use is_iterable():

if (is_iterable($mystery_type)) {
    // your loop
}

Or its polyfill (found in the documentation comments):

if (!function_exists('is_iterable')) {
    function is_iterable($obj) {
        return is_array($obj) || (is_object($obj) && ($obj instanceof \Traversable));
    }
}

Read more: iterable pseudo-type (PHP 7.1+)

like image 117
AymDev Avatar answered Oct 21 '25 22:10

AymDev


The best way is to not write methods that accept multiple types of data as input but to write smaller specific methods for each type of input. The code of such smaller methods is shorter, simpler, easier to read and understand (and to test).

The method for iterable data structures should use the Traversable interface as the type of its argument:

public function f(Traversable $input) {
    // This foreach is guaranteed to always work
    foreach ($input as $key => $value) {
        // Do something with $value and/or $key
    }
}

PHP triggers an error when method f() is invoked with a value that does not implement the Traversable interface.

like image 27
axiac Avatar answered Oct 21 '25 23:10

axiac