Oft passiert es mir, Daten zu behandeln, die entweder ein Array oder eine Nullvariable sein können, und einige foreach
mit diesen Daten zu füttern.
$values = get_values();
foreach ($values as $value){
...
}
Wenn Sie ein Foreach mit Daten versorgen, die kein Array sind, erhalten Sie eine Warnung:
Warnung: Ungültiges Argument für foreach () in [...]
Angenommen, es ist nicht möglich, die Funktion get_values()
so umzuwandeln, dass immer ein Array zurückgegeben wird (Abwärtskompatibilität, nicht verfügbarer Quellcode, aus welchem Grund auch immer), frage ich mich, auf welche Weise diese Warnungen am saubersten und effizientesten sind:
$values
in ein Array$values
in Array initialisierenforeach
mit einer if
Ich persönlich finde das am saubersten - nicht sicher, ob es am effizientesten ist, Verstand!
if (is_array($values) || is_object($values))
{
foreach ($values as $value)
{
...
}
}
Der Grund für meine Präferenz ist, dass kein leeres Array zugewiesen wird, wenn Sie sowieso nichts zum Anfang haben.
Wie wäre es mit diesem? viel sauberer und alles in einer Zeile.
foreach ((array) $items as $item) {
// ...
}
Ich verwende normalerweise ein ähnliches Konstrukt:
/**
* 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...
}
}
Beachten Sie, dass diese bestimmte Version nicht getestet wird, sondern direkt aus dem Speicher in SO eingegeben wird.
Edit: hinzugefügt Traversable check
Bitte verlassen Sie sich nicht auf das Casting als Lösung, Auch wenn andere dies als gültige Option zur Vermeidung eines Fehlers vorschlagen, kann dies zu einer anderen führen.
Achtung: Wenn Sie erwarten, dass eine bestimmte Form eines Arrays zurückgegeben wird, schlägt dies möglicherweise fehl. Dafür sind weitere Überprüfungen erforderlich.
Z.B. Wenn ein boolescher Wert in ein Array
(array)bool
umgewandelt wird, ergibt NICHT ein leeres Array, sondern ein Array mit einem Element, das den booleschen Wert als int enthält:[0=>0]
oder[0=>1]
.
Ich habe einen Schnelltest geschrieben, um dieses Problem darzustellen . (Hier ist ein backup Test falls die erste Test-URL fehlschlägt.)
Eingeschlossen sind Tests für: null
, false
, true
, eine class
, eine array
und undefined
.
Testen Sie Ihre Eingabe immer, bevor Sie sie in foreach verwenden. Vorschläge:
$array = is_array($var) or is_object($var) ? $var : [] ;
try{}catch(){}
-Blöcke verwendenarray_key_exists
für einen bestimmten Schlüssel verwenden, oder die Tiefe eines Arrays testen (wenn es eins ist!) .Versuche dies:
//Force array
$dataArr = is_array($dataArr) ? $dataArr : array($dataArr);
foreach ($dataArr as $val) {
echo $val;
}
;)
$values = get_values();
foreach ((array) $values as $value){
...
}
Das Problem ist immer null und Casting ist tatsächlich die Reinigungslösung.
Zunächst muss jede Variable initialisiert werden. Immer.
.__ Casting ist keine Option.
if get_values (); andere Typvariablen zurückgeben können, muss dieser Wert natürlich geprüft werden.
Kürzere Erweiterung des Codes von @ Kris
function secure_iterable($var)
{
return is_iterable($var) ? $var : array();
}
foreach (secure_iterable($values) as $value)
{
//do stuff...
}
besonders für die Verwendung von Template-Code
<?php foreach (secure_iterable($values) as $value): ?>
...
<?php endforeach; ?>
Wenn Sie php7 verwenden und nur undefinierte Fehler behandeln möchten, ist dies der sauberste IMHO
$array = [1,2,3,4];
foreach ( $array ?? [] as $item ) {
echo $item;
}
foreach ($arr ? $arr : [] as $elem) {
// Does something
}
Dies prüft nicht, ob es sich um ein Array handelt, überspringt jedoch die Schleife, wenn die Variable null oder ein leeres Array ist.
Wie wäre es mit dieser Lösung:
$type = gettype($your_iteratable);
$types = array(
'array',
'object'
);
if (in_array($type, $types)) {
// foreach code comes here
}
Ich bin mir nicht sicher, ob dies der Fall ist, aber dieses Problem scheint beim Migrieren von wordpress Sites oder beim Migrieren dynamischer Sites im Allgemeinen mehrmals aufzutreten. Wenn dies der Fall ist, stellen Sie sicher, dass das Hosting, auf das Sie migrieren, dieselbe PHP Version verwendet, die Ihre alte Site verwendet.
Wenn Sie Ihre Site nicht migrieren und dies nur ein Problem ist, versuchen Sie, ein Update auf PHP 5 durchzuführen. Dies behebt einige dieser Probleme. Könnte wie eine dumme Lösung erscheinen, hat aber den Trick für mich getan.
Ausnahmefall für diese Benachrichtigung tritt auf, wenn Sie das Array in der foreach-Schleife auf null setzen
if (is_array($values))
{
foreach ($values as $value)
{
$values = null;//WARNING!!!
}
}
Was ist mit der Definition eines leeren Arrays als Fallback, wenn get_value()
leer ist?
Ich kann mir keinen kürzesten Weg vorstellen.
$values = get_values() ?: [];
foreach ($values as $value){
...
}
Ich benutze eine Kombination aus empty, isset und is_array als
$array = ['dog', 'cat', 'lion'];
if(!empty($array) && isset($array) && is_array($array){
//loop
foreach ($array as $values) {
echo $values;
}
}
Es scheint auch einen Bezug zur Umwelt zu geben:
Ich hatte den Fehler "ungültiges Argument für foreach ()" nur in der dev-Umgebung, aber nicht in prod (ich arbeite auf dem Server, nicht localhost).
Trotz des Fehlers zeigte ein var_dump an, dass das Array gut vorhanden war (in beiden Fällen app und dev).
Die if (is_array($array))
um die foreach ($array as $subarray)
hat das Problem gelöst.
Tut mir leid, dass ich die Ursache nicht erklären kann, aber da ich eine Weile brauchte, um eine Lösung zu finden, dachte ich mir, dies als Beobachtung zu teilen.
Verwenden Sie die Funktion is_array, wenn Sie das Array an die foreach-Schleife übergeben.
if (is_array($your_variable)) {
foreach ($your_variable as $item) {
//your code
}
}
Warnung ungültiges Argument für foreach () display tweets angegeben . Gehe zu "/ wp-content/plugins/display-tweets-php" . Dann füge diesen Code in Zeilennummer 591 ein.
if (is_array($tweets)){
foreach ( $tweets as $Tweet )
{
...
}
}