Chcę użyć foreach
pętli ze zmienną, ale ta zmienna może mieć NULL
na przykład wiele różnych typów .
Więc zanim foreach
to przetestuję:
if(is_array($var)){
foreach($var as ...
Ale zdałem sobie sprawę, że może to być również klasa implementująca Iterator
interfejs. Może jestem niewidomy, ale jak sprawdzić, czy klasa implementuje interfejs? Czy jest coś takiego jak is_a
funkcja lub inherits
operator? Znalazłem class_implements
, mogę to wykorzystać, ale może jest coś prostszego?
Po drugie, co ważniejsze, przypuszczam, że ta funkcja istnieje, wystarczyłoby do sprawdzenia, czy zmienna is_array
lub „ Iterator
interfejs implementuje ”, czy też powinienem przetestować coś więcej?
Odpowiedzi:
Jeśli używasz
foreach
wewnątrz funkcji i spodziewasz się tablicy lub obiektu Traversable , możesz wpisać wskazówkę dotyczącą tej funkcji za pomocą:function myFunction(array $a) function myFunction(Traversable)
Jeśli nie używasz
foreach
wewnątrz funkcji lub spodziewasz się obu , możesz po prostu użyć tej konstrukcji, aby sprawdzić, czy możesz iterować po zmiennej:if (is_array($a) or ($a instanceof Traversable))
źródło
is_array
że jest drogi. Koszt obliczeniowy wydawał się wzrastać wraz z rozmiarem tablicy (co nie ma sensu, ponieważ sprawdza tylko, czy jest to tablica). Ale przydarzyło mi się to szokująco w bibliotece. Zobacz mój komentarz w powiązanym pytaniu. Będzieinstanceof Traversable
działać z tablicami? Nie miałem okazji przetestować jego działania.Traversable
tak.$var = array(1,2,3);
wynikami są:is_array($var) = true
i$var instanceof Traversable = false
.Iterator
i dlatego nie działają zTraversable
.foreach
może obsługiwać tablice i obiekty. Możesz to sprawdzić za pomocą:$can_foreach = is_array($var) || is_object($var); if ($can_foreach) { foreach ($var as ... }
Nie musisz specjalnie sprawdzać,
Traversable
ponieważ inni zasugerowali to w swoich odpowiedziach, ponieważ wszystkie obiekty - podobnie jak wszystkie tablice - są przejezdne w PHP.Bardziej technicznie:
( źródło )
Mówiąc najprościej w typowym programowaniu PHP, gdziekolwiek jest zmienna
i nie jest
możesz
foreach
na nim użyć .źródło
Możesz sprawdzić instancję
Traversable
za pomocą prostej funkcji. To by zadziałało na to wszystko zIterator
powoduIterator extends Traversable
function canLoop($mixed) { return is_array($mixed) || $mixed instanceof Traversable ? true : false; }
źródło
<?php $var = new ArrayIterator(); var_dump(is_array($var), ($var instanceof ArrayIterator));
zwraca
bool(false)
lubbool(true)
źródło
Funkcje
<?php /** * Is Array? * @param mixed $x * @return bool */ function isArray($x) : bool { return !isAssociative($x); } /** * Is Associative Array? * @param mixed $x * @return bool */ function isAssociative($x) : bool { if (!is_array($array)) { return false; } $i = count($array); while ($i > 0) { if (!isset($array[--$i])) { return true; } } return false; }
Przykład
<?php $arr = [ 'foo', 'bar' ]; $obj = [ 'foo' => 'bar' ]; var_dump(isAssociative($arr)); # bool(false) var_dump(isAssociative($obj)); # bool(true) var_dump(isArray($obj)); # bool(false) var_dump(isArray($arr)); # bool(true)
źródło
Od PHP 7.1 istnieje pseudo typ
iterable
służący dokładnie do tego celu. Podpowiedzi do typuiterable
akceptują dowolną tablicę, a także każdą implementacjęTraversable
interfejsu. PHP 7.1 również wprowadził tę funkcjęis_iterable()
. W przypadku starszych wersji zobacz inne odpowiedzi tutaj, aby przeprowadzić równoważne wymuszanie typu bez nowszych wbudowanych funkcji.Fair play: jak wskazał BlackHole, to pytanie wydaje się być duplikatem obiektów iterowalnych i podpowiedzi typu tablicy? a jego odpowiedź jest bardziej szczegółowa niż moja.
źródło