The best I could come up is
function is_array_alike($array) {
return is_array($array) || (is_object($array) && $array instanceof ArrayAccess && $array instanceof Traversable && $array instanceof Serializable && $array instanceof Countable);
}
Ugh. Is there something more pretty?
Edit: the test for is_object
seems unnecessary. I have added a section to the instanceof PHP manual about that.
There's a new spec out for PHP 7.3 that implements an
is_countable
function here https://wiki.php.net/rfc/is-countableBased on the spec & for previous PHP versions, you can use this
or you could also implement a sort of polyfill for that like this
Well, since you did use the word "pretty" in your post, just a quick suggestion on cosmetic changes for readability:
Explanation of changes:
Function name change: "
is_array_alike
" -> "is_array_or_alike
" just to make it clear that both array-ness and alike-ness are being tested.Param/arg name change:
$array
->$var
because "$array
" is already sort of presupposing that the argument is of type array.Stacking &&'ed conditions for readability and conformance to Drupal coding-standard: 80-char line max. Since you are one of the Drupal core maintainers I guess I am assuming this function might possibly go into Drupal, so probably you would have done this before committing anyway.
You are correct that the
is_object()
is unnecessary. In Java it would be necessary becauseinstanceof
would throw a compile-time error if the first operand weren't an object, but I checked just now in PHP and there is no error, just a result of bool(false).I second paulmatthews86's suggestion that you provide a use case. It's hard to provide recommendations if we don't know the criteria. For example, to borrow a bit from the duck-typing paradigm point of view, the
instanceof
tests would be useful but not necessarily mandatory or even complete. If you are more interested in what the$var
can do and how it behaves in certain contexts then you could use reflection to check for the existence of the methods that need to be invoked on it later, or you could test that it behaves as expected when passed to array functions. e.g. Does it "work" witharray_udiff_assoc
,array_chunk
, etc. If these behaviors are more important for your use cases then these tests might supersede theinstanceof
type-testing, although of course there would be a lot of overlap.Hope this helps. Interested to see what you finally decide upon if you decide to post it.
there is iterator interface in php http://php.net/manual/en/class.iterator.php
use
Even though
ArrayObject
implementsSerializable
, the assumption is wrong that an object must implement it to be array-like.The opposite is the case. You can make use of
Serializable
to effectively prevent the serialization of an object. So I would consider to remove it from the interface check.Also if you use
instanceof
without an object, you will see a (fatal) error. I suggest you delegate the check of an object that is "array-like" to a leaf function and make your function that is less strict with the input types make use of it:Also keep in mind, even an object is array-like, it does not work with most array functions. nor would it work well with
foreach
, so you should better outline about which array features you're looking for here.