Làm cách nào để kiểm tra xem biến có phải là mảng không?… Hoặc một cái gì đó giống như mảng


90

Tôi muốn sử dụng foreachvòng lặp với một biến, nhưng biến này có thể có nhiều kiểu khác nhau, NULLchẳng hạn.

Vì vậy, trước khi foreachtôi kiểm tra nó:

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

Nhưng tôi nhận ra rằng nó cũng có thể là một lớp thực thi Iteratorgiao diện. Có lẽ tôi mù tịt nhưng làm thế nào để kiểm tra xem lớp thực hiện giao diện? Có một cái gì đó giống như is_ahàm hoặc inheritstoán tử? Tôi tìm thấy class_implements, tôi có thể sử dụng nó, nhưng có lẽ có cái gì đó đơn giản hơn?

Và thứ hai, quan trọng hơn, tôi cho rằng hàm này tồn tại, liệu có đủ để kiểm tra xem biến is_arrayhoặc " Iteratorgiao diện thực hiện " hay tôi nên kiểm tra thêm thứ gì đó không?


2
if ($ var instanceof ArrayIterator)
Alexey

Yeah, tôi rất chắc chắn điều này sẽ không làm việc mà thậm chí còn không nhìn vào hướng dẫn ...
Voitcus

2
Có thể trùng lặp các đối tượng
Lỗ đen

Câu trả lời:


79

Nếu bạn đang sử dụng foreachbên trong một hàm và bạn đang mong đợi một mảng hoặc một traversable đối tượng bạn có thể gõ gợi ý rằng chức năng với:

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

Nếu bạn không sử dụng foreachbên trong một hàm hoặc bạn đang mong đợi cả hai, bạn có thể chỉ cần sử dụng cấu trúc này để kiểm tra xem bạn có thể lặp qua biến không:

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

Cảm ơn. Tôi hy vọng nó là đủ và sẽ không có / sẽ không có cấu trúc ngôn ngữ nào khác có thể được lặp lại.
Voitcus

Tôi đã thấy is_arraylà tốn kém. Chi phí tính toán dường như tăng theo kích thước của mảng (điều này không có ý nghĩa gì vì nó chỉ kiểm tra xem nó có phải là một mảng hay không). Nhưng nó đã xảy ra với tôi một cách kinh ngạc trong một thư viện. Xem bình luận của tôi trong câu hỏi được liên kết. Sẽ instanceof Traversablehoạt động với mảng? Tôi đã không có cơ hội để kiểm tra hiệu suất của nó.
ADTC

@ADTC AFAIR một mảng là một ví dụ của Traversablenhư vậy có.
Giày

1
@Shoe Tôi đã thử nó ở đây . Với $var = array(1,2,3);kết quả là: is_array($var) = true$var instanceof Traversable = false.
ADTC

@ADTC Vâng, vừa mới kiểm tra. Mảng không triển khai Iteratorvà do đó không hoạt động với Traversable.
Giày

15

foreachcó thể xử lý mảng và đối tượng. Bạn có thể kiểm tra điều này bằng:

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

Bạn không cần phải kiểm tra cụ thể Traversablenhư những người khác đã gợi ý điều đó trong câu trả lời của họ, bởi vì tất cả các đối tượng - như tất cả các mảng - đều có thể duyệt được trong PHP.

Về mặt kỹ thuật:

foreachhoạt động với tất cả các loại có thể duyệt, tức là với mảng, với các đối tượng thuần túy (nơi các thuộc tính có thể truy cập được duyệt qua) và Traversablecác đối tượng (hoặc đúng hơn là các đối tượng xác định get_iteratortrình xử lý nội bộ ).

( nguồn )

Nói một cách đơn giản trong lập trình PHP thông thường, bất cứ khi nào một biến

  • một mảng
  • một đối tượng

không

  • VÔ GIÁ TRỊ
  • một nguồn lực
  • một vô hướng

bạn có thể sử dụng foreachnó.


5

Bạn có thể kiểm tra phiên bản của Traversablebằng một hàm đơn giản. Điều này sẽ hoạt động cho tất cả những điều này Iteratorbởi vìIterator extends Traversable

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

Phần "? true: false" là thừa. instanceof đã cung cấp một giá trị bool.
Linas

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

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

trả lại bool(false)hoặcbool(true)


0

Chức năng

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

Thí dụ

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

Vì PHP 7.1 có một kiểu giả iterablecho chính xác mục đích này. Type-hinting iterablechấp nhận bất kỳ mảng nào cũng như bất kỳ triển khai nào của Traversablegiao diện. PHP 7.1 cũng đã giới thiệu chức năng này is_iterable(). Đối với các phiên bản cũ hơn, hãy xem các câu trả lời khác tại đây để hoàn thành việc thực thi kiểu tương đương mà không cần các tính năng tích hợp mới hơn.

Chơi công bằng: Như BlackHole đã chỉ ra, câu hỏi này có vẻ là một bản sao của các đối tượng có thể lặp lại được và gợi ý về kiểu mảng? câu trả lời của anh ấy hoặc cô ấy đi vào chi tiết hơn của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.