PHP PHP Warning: Illegal offset type in isset or empty

Schumiel

Lieutenant
Registriert
Jan. 2010
Beiträge
846
Hallo,

ich möchte ein Kalender umsetzen und bekomme immer folgenden Fehler:

PHP Warning: Illegal offset type in isset or empty

Die Zeile $days[$key]['test'] = $tests; ist dafür verantwortlich:

PHP:
foreach($days AS $key => $day) {
           if($day["day"]) {
               $tests = $this->testRepository->findTestByCal($day["day"],$nav["month-current"],$nav["year-current"]);
               $testCount             = count($tests);
               $days[$key]['test']   = $tests;
               $days[$key]["count"]    = $testCount;
           }
       }

public function findTestByCal($day = NULL, $month = NULL, $year = NULL) {

       $query = $this->createQuery();
       $query->getQuerySettings()->setRespectStoragePage(FALSE);
       return $query->execute(true);
   }

Debug auf $days ergibt folgendes Ergebnis (gekürzt):

PHP:
array(35 items)
   0 => array(3 items)
   1 => array(3 items)
   2 => array(3 items)
   3 => array(3 items)
      day => 4 (integer)
      test => array(3 items)
         0 => array(45 items)
            uid => 141 (integer)
            pid => 125 (integer)
         1 => array(45 items)
            uid => 142 (integer)
            pid => 125 (integer)

Ich kann dies normal benutzen. Jedoch stören mich die Warnings, die nun 35mal aufpluppen.
Wie kann man das lösen?
 
Vorher pruefen ob der jeweilige Index im Array ueberhaupt existiert.
PHP:
if(isset($days[$key])) {
    if(isset($days[$key]['test'])) {
        $days[$key]['test'] = $tests;
    }
    if(isset($days[$key]['count'])) {
        $days[$key]["count"] = $testCount;
    }
}
 
  • Gefällt mir
Reaktionen: Sgt_H4rtman
r15ch13 schrieb:
Vorher pruefen ob der jeweilige Index im Array ueberhaupt existiert.
PHP:
if(isset($days[$key])) {
    if(isset($days[$key]['test'])) {
        $days[$key]['test'] = $tests;
    }
    if(isset($days[$key]['count'])) {
        $days[$key]["count"] = $testCount;
    }
}

isset kann man schachteln, heisst statt der zwei ifs einfach den vollen Pfad im Array prüfen. Isset sorgt selbständig dafür, dass alle Ebenen geprüft werden.

PHP:
if(isset($days[$key]['test'])) {
    $days[$key]['test'] = $tests;
}
if(isset($days[$key]['count'])) {
    $days[$key]["count"] = $testCount;
}
 
  • Gefällt mir
Reaktionen: Andreas_ und r15ch13
isset() ist hier nicht die Lösung, da sonst nie ein 'test'/'count'-Eintrag hinzugefügt wird, wenn er nicht schon vorhanden ist.

@Schumiel Bist du dir sicher, dass du diese Meldung mit diesem Code an dieser Stelle bekommst? Was passiert, wenn du den Code wie folgt änderst
Code:
       foreach($days AS $key => &$day) {
           if($day["day"]) {
               ...
               $day['test']   = $tests;
               $day["count"]    = $testCount;
           }
       }
Beachte das & bei &$day. Welche php-Version nutzt du?
 
Nein, es existiert nicht. Ich möchte es ja mit der Variable $tests bestücken.
 
Der Fehler PHP Warning: Illegal offset type in isset or empty wird geworfen, wenn ein Array oder Object als Array-Key verwendet wird. Sicher, dass in $Days[...]['day'] und / oder in $key immer ein Wert vom Typ String / Integer oder NULL steht?
 
  • Gefällt mir
Reaktionen: Sgt_H4rtman
Schau mal hier bei Stackoverflow. Der Ersteller dort hatte ein ähnliches Problem und es stellte sich heraus, dass in einer weiteren Iteration dann kein String/Int mehr in der Indexvariablen steckte.

Nutze für solche Fälle am besten Xdebug mit VSCode oder PhpStorm. Da kannst du den Breakpoints Bedingungen mitgeben und im Stacktrace ermitteln, wo deine Variable mutiert wurde.
 
Ich bin mir ziemlich sicher, dass es an $days[$key]["test"] = $tests; liegt und nicht an dem $key.
Denn $days[$key]["count"] = $testCount; macht keine Probleme, weil dort ein String oder Int drin steht. Sobald das aber ein weitere Array ist, knallt es. Aber sowas sollte doch kein Problem sein?
 
PHP:
Core: Error handler (FE): PHP Warning: Illegal offset type in /html/***.php line 53
Zeile 53 ist genau die Zeile, wie im Anfang erwähnt.
 
Bitte guck dir nochmal meinen post #4 an.
Falls das nichts bringt: wenn du das $tests in $days[$key]["test"] = $tests; durch array() ersetzt kommt dann auch eine Warnung?
 
Sorry, habe deine #4 Beitrag total übersehen. Wenn ich das mache, was du dort geschrieben hast, stimmt mein array nicht mehr. tests und count kommen erst nach den anderen interierten 35.
Wenn ich statt $tests eine Zahl oder ein String oder ein array() einfüge, kommt die Meldung nicht. Es liegt als an den $tests. Aber in meinem ersten Beitrag sieht man das Ergebnis. Daran ist doch nichts falsch?
 
Schumiel schrieb:
Wenn ich das mache, was du dort geschrieben hast, stimmt mein array nicht mehr. tests und count kommen erst nach den anderen interierten 35.
Zeig mal den Code und das var_dump($days); dazu.
Auch ein var_dump($tests); wäre mal interessant, weil da stimmt wohl etwas nicht.
 
Sgt_H4rtman schrieb:
isset kann man schachteln, heisst statt der zwei ifs einfach den vollen Pfad im Array prüfen. Isset sorgt selbständig dafür, dass alle Ebenen geprüft werden.

PHP:
if(isset($days[$key]['test'])) {
    $days[$key]['test'] = $tests;
}
if(isset($days[$key]['count'])) {
    $days[$key]["count"] = $testCount;
}

Ne kann man nicht schachteln, ein isset($x['bla']['suelz']) wirft nen Fehler wenn $x['bla'] nicht gesetzt ist. Man kann aber isset($x['bla'], $x['bla']['suelz']) machen, das wirft keinen Fehler.
 
Das ist aber nach dem Schleifendurchlauf? Interessant ist doch, was in $tests steht, bevor das hinzugefügt wird. Bei einigen Elementen gibt es offensichtlich ein Problem.
Was du noch probieren könntest: Beim zuweisen von $tests zum array ein & davor setzen, also $days[$key]["test"] = &$tests;
 
Mit &$tests ist der Fehler weg, aber der Inhalt davon auch.

In $tests ist folgendes drin (gekürzt):

Code:
array(3 items)
   0 => array(45 items)
      uid => 146 (integer)
      pid => 114 (integer)
   1 => array(45 items)
      uid => 147 (integer)
      pid => 114 (integer)
   2 => array(45 items)
      uid => 148 (integer)
      pid => 114 (integer)

Sind alles nur String, int oder NULL.
 
mambokurt schrieb:
Ne kann man nicht schachteln, ein isset($x['bla']['suelz']) wirft nen Fehler wenn $x['bla'] nicht gesetzt ist. Man kann aber isset($x['bla'], $x['bla']['suelz']) machen, das wirft keinen Fehler.

Gerade in der interaktiven Shell nochmal probiert:
PHP:
error_reporting(E_ALL);
$foo = ['bar' => ['foo' => true]];

// this is ok > bool(true)
var_dump(isset($foo['bar']['foo']));
// this is ok too > bool(false)
var_dump(isset($foo['baz']['foo']));
// this is not ok > Notice: Undefined index: baz in php shell code on line
var_dump($foo['baz']['foo']);

Meine Aussage stimmt also. Im übrigen ist dies auch eine Inspection in PhpStorm mit PHP Inspections (EA Extended) Plugin. Ich habe mir das also nicht ausgedacht.

BTT:
@Schumiel hast du die Möglichkeit, das mit einem Debugger (XDebug) in PHPStorm oder VsCode zu testen? Bzw.: Wenn du weißt dass der Fehler dort liegt, dann lass dir doch mal per var_dump in jedem Durchlauf die Typen für $key und $tests ausgeben. Der Fehler ist eigentlich ziemlich eindeutig. Unter Umständen steckt in $key auf einmal ein Float, weil du noch damit etwas berechnest. Ich vermute mal, du hast nicht den gesamten Code der Schleife gepostet.
 
Zuletzt bearbeitet:
Wenn es an am $key liegen würde, müsste mir $days[$key]["count"] = $testCount; auch eine Warnung werfen. Ja, es ist nicht das var_dump, weil dieser zu lang ist. Aber ich versichere, dass da nur sting, int und null drin ist.
Ergänzung ()

Hier mal der Auszug aus $tests ...
PHP:
      uid => 128 (integer)
      pid => 114 (integer)
      tstamp => 1553012182 (integer)
      crdate => 1553012136 (integer)
      cruser_id => 9 (integer)
      deleted => 0 (integer)
      hidden => 0 (integer)
      test => 0 (integer)
      test => 0 (integer)
      test => '...' (24 chars)
      test => '...' (369 chars)
      test => 1554190200 (integer)
      test => 1554305400 (integer)
      test => '1.00' (4 chars)
      test => 1 (integer)
      test => '3.16' (4 chars)
      test => '...' (151 chars)
      test => '...' (1966 chars)
      test => 0 (integer)
      test => '...' (386 chars)
      test => '0' (1 chars)
      test => 0 (integer)
      test => 0 (integer)
      test => NULL
      test => 5 (integer)
      test => 6992 (integer)
      test => 1 (integer)
      test => 0 (integer)
      test => 2 (integer)
      test => '0' (1 chars)
      test => 7 (integer)
      test => 0 (integer)
      test => 0 (integer)
      test => 1 (integer)
      test => 0 (integer)
      test => 1 (integer)
      test => 9 (integer)
      test => 0 (integer)
      test => 0 (integer)
      test => 0 (integer)
      test => 1 (integer)
      test => '' (0 chars)
      test => 0 (integer)
      test => '' (0 chars)
      test => 0 (integer)
 
Zuletzt bearbeitet:
Das ist ja teil einer Klasse und kein prozeduraler Code.
Wenn du nicht den ganzen Stacktrace des Fehlers posten willst (wegen Geheimnis etc.), dann schau ihn dir wenigstens selber an. Sonst kommen wir nicht weiter.

In der normalen, prozeduralen Ausführung ist jedenfalls kein Fehler zu erkennen. Ich habe das, so gut ich konnte, nach gebaut und kann die Warnung unter keinen Umständen produzieren. Also wird der Fehler innerhalb des Stacks auftreten, durch die Zuweisung von $days[$key]['test'] = $tests = $this->testRepository->findTestByCal(...). Der Fehler kann viel tiefer in den Klassen stecken, als du aktuell vermutest.

Edit: Am besten kapselst du das mal so:

PHP:
set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) {
    if (0 === error_reporting()) {
        return false;
    }

    throw new ErrorException ($errstr, 0, $errno, $errfile, $errline);
});

try {
    foreach ($days AS $key => $day) {
        if ($day["day"]) {
            $tests = ...;
            $testCount = count($tests);
            $days[$key]['test'] = $tests;
            $days[$key]['count'] = $testCount;
        }
    }
} catch (ErrorException  $e) {
    echo $e->getMessage().PHP_EOL;
    echo $e->getTraceAsString();
}

Da kommt dann bei einer provozierten PHP-Warnung bei mir z.B. folgendes heraus:

Code:
count(): Parameter must be an array or an object that implements Countable
#0 /var/www/htdocs/020-default/test.php(75): {closure}(2, 'count(): Parame...', '/var/www/htdocs...', 75, Array)
#1 {main}

Wichtig ist der set_error_handler mit der ErrorException (nicht zu verwechseln mit einer normalen Exception), da Warnungen ansonsten keine Exception auslösen.
 
Zuletzt bearbeitet:
Zurück
Oben