web-dev-qa-db-ja.com

Foreach()に無効な引数が指定されました

多くの場合、配列またはNULL変数のいずれかである可能性があるデータを処理し、これらのデータを使用してforeachを渡すことがあります。

$values = get_values();

foreach ($values as $value){
  ...
}

配列ではないデータをforeachに入力すると、警告が表示されます。

警告:[...]のforeach()に無効な引数が指定されています

常に配列を返すようにget_values()関数をリファクタリングすることは不可能であると仮定して(後方互換性、利用できないソースコード、その他の理由にかかわらず)、これらの警告を避けるための最もクリーンで最も効率的な方法は疑問に思います。

  • $valuesを配列にキャスト
  • $valuesを配列に初期化する
  • foreachifでラップする
  • その他(提案してください)
266
Roberto Aloi

個人的に私はこれが最もきれいであると思います - それが最も効率的であるかどうかわからない、心!

if (is_array($values) || is_object($values))
{
    foreach ($values as $value)
    {
        ...
    }
}

私の好みの理由は、あなたがとにかく始めに何もないときには空の配列を割り当てないことです。

455
Andy Shellam

これはどう?もっときれいにそしてすべて一列に。

foreach ((array) $items as $item) {
 // ...
 }
90
Ajith R Nair

私は通常これに似た構造を使用します:

/**
 * Determine if a variable is iterable. i.e. can be used to loop over.
 *
 * @return bool
 */
function is_iterable($var)
{
    return $var !== null 
        && (is_array($var) 
            || $var instanceof Traversable 
            || $var instanceof Iterator 
            || $var instanceof IteratorAggregate
            );
}

$values = get_values();

if (is_iterable($values))
{
    foreach ($values as $value)
    {
        // do stuff...
    }
}

この特定のバージョンはテストされておらず、メモリからSOに直接型付けされていることに注意してください。

編集: added 移動可能 check

40
Kris

解決策としてのキャストに頼らないでください、他の人がこれをエラーを防ぐための有効なオプションとして提案しているとしても、それが別のものを引き起こすかもしれません。

注意:特定の形式の配列が返されることが予想される場合、これは失敗する可能性があります。それにはさらに検査が必要です。

例えば。ブール値を配列(array)boolにキャストすると、ではなく空の配列になりますが、ブール値をintとして含む1つの要素を持つ配列:[0=>0]または[0=>1]になります。

私はこの問題を提示するための簡単なテストを書いた 。 (最初のテストURLが失敗した場合のための バックアップテスト です。)

nullfalsetrueclassarrayおよびundefinedに対するテストが含まれています。


foreachで使用する前に必ず入力をテストしてください。提案:

  1. クイック型チェック$array = is_array($var) or is_object($var) ? $var : [] ;
  2. foreachを使用する前のメソッド内の 型ヒント配列 および 戻り型の指定
  3. Foreachをif内にラップ
  4. try{}catch(){}ブロックを使う
  5. 製品版リリース前の適切なコードの設計/テスト
  6. 適切な形式に対して配列をテストするには、特定のキー または配列の深さをテストする(それが1の場合) _でarray_key_existsを使用できます。
  7. 重複コードを減らす方法で、常にヘルパーメソッドをグローバル名前空間に抽出します。
13
AARTT

これを試して:

//Force array
$dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
foreach ($dataArr as $val) {
  echo $val;
}

;)

$values = get_values();

foreach ((array) $values as $value){
  ...
}

問題は常に無効で、キャスティングは実際には洗浄液です。

4
boctulus

まず第一に、すべての変数は初期化されなければなりません。常に。
キャスティングは選択肢ではありません。
if get_values();異なる型の変数を返すことができます、もちろんこの値をチェックする必要があります。

3

@ Kris's code /のより簡潔な拡張

function secure_iterable($var)
{
    return is_iterable($var) ? $var : array();
}

foreach (secure_iterable($values) as $value)
{
     //do stuff...
}

特に内側のテンプレートコードを使用するため

<?php foreach (secure_iterable($values) as $value): ?>
    ...
<?php endforeach; ?>
3
HongKilDong

あなたがphp7を使っていて、未定義のエラーだけを処理したいのなら、これは最もきれいな私見です。

$array = [1,2,3,4];
foreach ( $array ?? [] as $item ) {
  echo $item;
}
2
foreach ($arr ? $arr : [] as $elem) {
    // Does something 
}

これが配列かどうかはチェックしませんが、変数がnullまたは空の配列の場合はループをスキップします。

2
T30

この解決策はどうですか。

$type = gettype($your_iteratable);
$types = array(
    'array',
    'object'
);

if (in_array($type, $types)) {
    // foreach code comes here
}
1
Julian

これが当てはまるかどうかはわかりませんが、ワードプレスサイトや動的サイトの移行時にこの問題が何度も発生するようです。このような場合は、移行先のホスティングが古いサイトで使用しているのと同じPHPバージョンを使用していることを確認してください。

あなたがあなたのサイトを移行しておらず、これが単なる問題である場合は、PHP 5に更新してみてください。これは、これらの問題のいくつかを解決します。ばかげた解決策のように見えるかもしれませんが、私にとってはトリックでした。

1
Erik

Foreachループ内で配列をnullに設定した場合、この通知に対する例外的なケースが発生します。

if (is_array($values))
{
    foreach ($values as $value)
    {
        $values = null;//WARNING!!!
    }
}
1
Farid Movsumov

get_value()が空の場合、空の配列を代替として定義するのはどうでしょうか。
最短の方法を考えることはできません。

$values = get_values() ?: [];

foreach ($values as $value){
  ...
}
0
Quentin Veron

私はempty、isset、is_arrayを組み合わせて使います。

$array = ['dog', 'cat',  'lion'];

if(!empty($array)  && isset($array)  && is_array($array){
//loop
foreach ($array as $values) {
echo $values; 
}
}
0

環境との関係もあるようです。

私は "invalid argument provided foreach()"エラーが発生したのは開発環境だけで、prodにはありません(私はlocalhostではなくサーバー上で作業しています)。

エラーがあるにもかかわらず、var_dumpは配列がそこにあることを示しました(どちらの場合もappとdev)。

if (is_array($array))の周りのforeach ($array as $subarray)は問題を解決しました。

申し訳ありませんが、原因を説明することはできませんが、解決策を見つけるまでに時間がかかるため、これを観察として共有することをお勧めします。

0
araldh

配列をforeachループに渡す場合は、is_array関数を使用してください。

if (is_array($your_variable)) {
  foreach ($your_variable as $item) {
   //your code
}
}
0
Super Model

Foreach()に与えられた警告無効な引数がツイートを表示します。 "/ wp-content/plugins/display-ツイート-php"に行きます。それから行番号591にこのコードを挿入してください、それは完全に動きます。

if (is_array($tweets)){  
        foreach ( $tweets as $Tweet ) 
    {
        ...
    }
}
0
Saad Khanani