変数が配列かどうかを確認するにはどうすればよいですか?…または配列のようなもの


90

foreach変数でループを使用したいのですが、この変数はNULL、たとえば、さまざまなタイプにすることができます。

foreachテストする前に:

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

しかし、それはIteratorインターフェースを実装するクラスにもなり得ることに気づきました。多分私は盲目ですが、クラスがインターフェイスを実装しているかどうかを確認するにはどうすればよいですか?is_a関数やinherits演算子のようなものはありますか?見つけましたclass_implements、それを使用できますが、もっと簡単なものがあるのでしょうか?

次に、より重要なことですが、この関数は存在すると思います。変数is_arrayまたは「Iteratorインターフェースを実装する」かどうかを確認するには十分でしょうか、それとも何かテストする必要がありますか?


2
if($ var instanceof ArrayIterator)
Alexey

ええ、私はこれがマニュアルさえ見ていないとうまくいかないと確信していました...
Voitcus

回答:


79

foreach関数内で使用していて、配列またはTraversableオブジェクトが必要な場合は、その関数のヒントを次のように入力できます。

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

foreach関数内で使用していない場合、または両方想定している場合は、この構文使用して、変数を反復できるかどうかを確認できます。

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

ありがとう。私はそれで十分であり、繰り返されることができる他の言語構造が存在する/存在しないことを願っています。
Voitcus 2013年

私はis_array高いことがわかりました。計算コストは​​、配列のサイズとともに増加するように見えました(配列であるかどうかを確認するだけなので意味がありません)。しかし、それは図書館で衝撃的に起こりました。リンクされた質問で私のコメントを参照しください。ウィルinstanceof Traversable配列を扱いますか?パフォーマンスをテストする機会がありませんでした。
ADTC

@ADTC AFAIR配列はそのインスタンスなTraversableので、はい。
2016

1
@Shoe ここで試してみまし$var = array(1,2,3);結果である:is_array($var) = true$var instanceof Traversable = false
ADTC

@ADTCうん、チェックしたばかり。配列は実装されIteratorていないため、では機能しませんTraversable
2016

15

foreach配列とオブジェクトを処理できます。これは次の方法で確認できます。

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

Traversable他の人が答えでそれをほのめかしたので、特にチェックする必要はありません。すべての配列のように、すべてのオブジェクトがPHPでトラバース可能だからです。

より技術的に:

foreachあらゆる種類のトラバーサル、つまり配列、プレーンオブジェクト(アクセス可能なプロパティがトラバースされる)およびTraversableオブジェクト(または内部get_iteratorハンドラーを定義するオブジェクト)で動作します。

ソース

一般的なPHPプログラミングでは、変数が常に

  • 配列
  • オブジェクト

そしてではない

  • ヌル
  • リソース
  • スカラー

あなたはそれに使うことができますforeach


5

Traversable簡単な関数でのインスタンスを確認できます。これはこのすべてのIteratorために働くでしょうIterator extends Traversable

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

「?true:false」の部分は冗長です。instanceofはすでに結果としてブール値を提供しています。
Linas

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

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

リターンbool(false)またはbool(true)


0

関数

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

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

PHP 7.1以降iterable、まさにこの目的のための疑似タイプがあります。型ヒントiterableは、任意の配列とTraversableインターフェイスの実装を受け入れます。PHP 7.1でもこの関数が導入されましたis_iterable()。古いバージョンの場合、新しい組み込み機能を使用せずに同等のタイプを適用するには、他の回答を参照してください。

公平なプレー:BlackHoleが指摘したように、この質問はIterableオブジェクトと配列型のヒントの複製のように見えますか?そして彼または彼女の答えは私のものよりも詳細に行きます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.