Bagaimana cara memeriksa apakah variabel adalah array?… Atau sesuatu seperti array


90

Saya ingin menggunakan foreachloop dengan variabel, tetapi variabel ini dapat memiliki banyak jenis, NULLmisalnya.

Jadi sebelum foreachsaya mengujinya:

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

Tetapi saya menyadari bahwa itu juga bisa menjadi kelas yang mengimplementasikan Iteratorantarmuka. Mungkin saya buta tapi bagaimana cara memeriksa apakah kelas mengimplementasikan antarmuka? Apakah ada sesuatu seperti is_afungsi atau inheritsoperator? Saya menemukan class_implements, saya dapat menggunakannya, tetapi mungkin ada sesuatu yang lebih sederhana?

Dan kedua, yang lebih penting, saya kira fungsi ini ada, akan cukup untuk memeriksa apakah variabel is_arrayatau "mengimplementasikan Iteratorantarmuka" atau haruskah saya menguji sesuatu yang lebih?


2
if ($ var instanceof ArrayIterator)
Alexey

Ya, saya sangat yakin ini tidak akan berhasil yang bahkan belum melihat ke manual ...
Voitcus

Jawaban:


80

Jika Anda menggunakan foreachinside sebuah fungsi dan Anda mengharapkan sebuah array atau objek Traversable, Anda dapat mengetik petunjuk yang berfungsi dengan:

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

Jika Anda tidak menggunakan foreachinside sebuah fungsi atau mengharapkan keduanya, Anda dapat menggunakan konstruksi ini untuk memeriksa apakah Anda dapat melakukan iterasi pada variabel:

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

Terima kasih. Saya berharap itu cukup dan tidak akan ada konstruksi bahasa lain yang dapat diulang.
Voitcus

Saya merasa is_arraymahal. Biaya komputasi sepertinya meningkat dengan ukuran array (yang tidak masuk akal karena hanya memeriksa apakah itu array). Tapi itu terjadi pada saya secara mengejutkan di perpustakaan. Lihat komentar saya di pertanyaan terkait. Akan instanceof Traversablebekerja dengan array? Saya tidak sempat menguji performanya.
ADTC

@ADTC AFAIR array adalah turunan dari Traversablejadi ya.
Sepatu

1
@Shoe Saya mencobanya di sini . Dengan $var = array(1,2,3);hasil sebagai berikut: is_array($var) = truedan $var instanceof Traversable = false.
ADTC

@ADTC Ya, baru saja diperiksa. Array tidak diimplementasikan Iteratordan karenanya tidak berfungsi Traversable.
Sepatu

15

foreachdapat menangani array dan objek. Anda dapat memeriksanya dengan:

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

Anda tidak perlu memeriksanya secara khusus karena Traversableorang lain telah mengisyaratkan dalam jawaban mereka, karena semua objek - seperti semua array - dapat dilintasi dalam PHP.

Lebih teknis:

foreachbekerja dengan semua jenis traversable, yaitu dengan array, dengan objek biasa (di mana properti yang dapat diakses dilintasi) dan Traversableobjek (atau lebih tepatnya objek yang mendefinisikan get_iteratorpenangan internal ).

( sumber )

Secara sederhana dikatakan dalam pemrograman PHP umum, setiap kali ada variabel

  • sebuah larik
  • Sebuah Objek

dan tidak

  • BATAL
  • sebuah sumber daya
  • skalar

Anda dapat menggunakannya foreach.


5

Anda dapat memeriksa instance Traversabledengan fungsi sederhana. Ini akan berhasil untuk semua ini IteratorkarenaIterator extends Traversable

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

"? true: false" bagian adalah redundan. instanceof sudah memberikan nilai bool sebagai hasilnya.
Linas

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

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

kembali bool(false)ataubool(true)


0

Fungsi

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

Contoh

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

Sejak PHP 7.1 ada tipe pseudo iterableuntuk tujuan ini. Mengisyaratkan tipe iterablemenerima larik apa pun serta implementasi Traversableantarmuka apa pun. PHP 7.1 juga memperkenalkan fungsi tersebut is_iterable(). Untuk versi yang lebih lama, lihat jawaban lain di sini untuk menyelesaikan penerapan jenis yang setara tanpa fitur bawaan yang lebih baru.

Permainan yang adil: Seperti yang ditunjukkan BlackHole, pertanyaan ini tampaknya merupakan duplikat dari objek Iterable dan petunjuk tipe array? dan jawabannya lebih detail dari saya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.