Come verificare se la variabile è un array? ... o qualcosa di simile a un array


90

Voglio usare un foreachciclo con una variabile, ma questa variabile può essere di molti tipi diversi, NULLper esempio.

Quindi, prima di foreachprovarlo:

if(is_array($var)){
  foreach($var as ...

Ma ho capito che può anche essere una classe che implementa l' Iteratorinterfaccia. Forse sono cieco, ma come verificare se la classe implementa l'interfaccia? C'è qualcosa come is_afunzione o inheritsoperatore? Ho trovato class_implements, posso usarlo, ma forse c'è qualcosa di più semplice?

E in secondo luogo, più importante, suppongo che questa funzione esista, sarebbe sufficiente per verificare se la variabile is_arrayo "implementa l' Iteratorinterfaccia" o dovrei provare qualcosa di più?


2
if ($ var instanceof ArrayIterator)
Alexey

Sì, ero così sicuro che non avrebbe funzionato che non ho nemmeno guardato il manuale ...
Voitcus

Risposte:


79

Se stai usando foreachall'interno di una funzione e ti aspetti un array o un oggetto Traversable , puoi digitare un suggerimento per quella funzione con:

function myFunction(array $a)
function myFunction(Traversable)

Se non stai usando foreachall'interno di una funzione o ti aspetti entrambi , puoi semplicemente usare questo costrutto per verificare se puoi iterare sulla variabile:

if (is_array($a) or ($a instanceof Traversable))

Grazie. Spero sia sufficiente e non ci sono / ci saranno altri costrutti linguistici che possono essere iterati.
Voitcus

L'ho trovato is_arraycostoso. Il costo computazionale sembrava aumentare con la dimensione dell'array (il che non ha senso dato che sta solo controllando se si tratta di un array). Ma a me è successo in modo scioccante in una biblioteca. Vedi il mio commento nella domanda collegata. Funzionerà instanceof Traversablecon gli array? Non ho avuto la possibilità di testarne le prestazioni.
ADTC

@ADTC AFAIR un array è un'istanza di Traversablequindi sì.
Scarpa

1
@Shoe l'ho provato qui . Con $var = array(1,2,3);i risultati sono: is_array($var) = truee $var instanceof Traversable = false.
ADTC

@ADTC Sì, appena controllato. Gli array non vengono implementati Iteratore quindi non funzionano con Traversable.
Scarpa

15

foreachpuò gestire array e oggetti. Puoi verificarlo con:

$can_foreach = is_array($var) || is_object($var);
if ($can_foreach) {
    foreach ($var as ...
}

Non è necessario controllare in modo specifico Traversablecome altri hanno suggerito nelle loro risposte, perché tutti gli oggetti, come tutti gli array, sono attraversabili in PHP.

Più tecnicamente:

foreachfunziona con tutti i tipi di traversabili, cioè con array, con oggetti semplici (dove vengono attraversate le proprietà accessibili) e Traversableoggetti (o meglio oggetti che definiscono il get_iteratorgestore interno ).

( fonte )

Detto semplicemente nella comune programmazione PHP, ogni volta che una variabile è

  • un array
  • un oggetto

e non lo è

  • NULLO
  • una risorsa
  • uno scalare

puoi usarlo foreach.


5

Puoi controllare l'istanza di Traversablecon una semplice funzione. Questo funzionerebbe per tutto questo IteratorperchéIterator extends Traversable

function canLoop($mixed) {
    return is_array($mixed) || $mixed instanceof Traversable ? true : false;
}

La parte "? true: false" è ridondante. instanceof fornisce già un valore bool come risultato.
Linas

2
<?php
$var = new ArrayIterator();

var_dump(is_array($var), ($var instanceof ArrayIterator));

restituisce bool(false)obool(true)


0

Funzioni

<?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;
}

Esempio

<?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)

0

A partire da PHP 7.1 esiste uno pseudo-tipo iterableproprio per questo scopo. Il suggerimento sul tipo iterableaccetta qualsiasi array e qualsiasi implementazione Traversabledell'interfaccia. Anche PHP 7.1 ha introdotto la funzione is_iterable(). Per le versioni precedenti, vedere altre risposte qui per ottenere l'applicazione del tipo equivalente senza le nuove funzionalità integrate.

Fair play: come ha sottolineato BlackHole, questa domanda sembra essere un duplicato di oggetti iterabili e suggerimenti sul tipo di array? e la sua risposta va più in dettaglio della mia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.