Richard: Invalid argument supplied for foreach()

Hallo,

ich programmieren gerade ein einfaches threadbasiertes Forum. Ich habe bis jetzt nur testweise eine Klasse Thread, deren Methode drawThread() die Threadstruktur "zeichnet". Das funktioniert soweit auch alles wunderbar, nur bekomme ich nach jedem Posting die im Titel angegebene Warnung "Warning: Invalid argument supplied for foreach() in C:\web\Apache2\htdocs\OOP\class.php on line 11".

Hier erstmal der Code der Klasse:

  
final class Thread {  
  
    private $marginUnit = 20;  
  
    public function drawThread( $posting, $mid ) {  
  
            $margin = $this->getMargin( $mid );  
            echo "<span style=\"margin-left:$margin" . "px" . "\">" . $posting . "</span>";  
            /* HIER KOMMT DIE WARNUNG */foreach( $this->getChildren( $mid ) as $child ) {  
                $this->drawThread( $child );  
            }  
  
    }  
  
    public function getPostings() {  
        return array(  
            "20060715t1m1rel0" => "Ausgangsposting",  
            "20060715t1m2rel1m1" => "Erste Antwort auf das Ausgangsposting",  
            "20060715t1m3rel1m1" => "Zweite Antwort auf das OP",  
            "20060715t1m4rel2m3" => "Antwort auf Zweite Antwort"  
        );  
    }  
  
    private function getChildren( $mid ) {  
        $children = array();  
        $RE_getMessageRelation = "/[0-9]{8}t[0-9]+m([0-9])+rel[0-9]+m[0-9]+/";  
        $RE_getRelated = "/[0-9]{8}t[0-9]+m[0-9]+rel[0-9]+m([0-9])+/";  
        preg_match( $RE_getMessageRelation, $mid, $messageNumber );  
        foreach( $this->getPostings() as $mid => $posting ) {  
            preg_match( $RE_getRelated, $mid, $relationNumber );  
            if( ( $relationNumber && $messageNumber ) ) {  
                if( $relationNumber[1] == $messageNumber[1] ) {  
                    $children[$mid] = $posting;  
                }  
            }  
        }  
    }  
  
    private function getMargin( $mid ) {  
        $RE_getRelation = "/[0-9]{8}t[0-9]+m[0-9]+rel([0-9]+)m[0-9]+/";  
        preg_match( $RE_getRelation, $mid, $relation );  
        if( $relation ) {  
            return $relation[1] * $this->marginUnit;  
        } else {  
            return 0;  
        }  
    }  
  
}  
  
$thread = new Thread();  
  
$postings = $thread->getPostings();  
foreach( $postings as $mid => $posting ) {  
    $thread->drawThread( $posting, $mid );  
}  

Entschuldigt, dass ich euch einen solchen Batzen vor den Kopf knalle, aber da hier jeden Methode mit jeder verstrickt ist, wusste ich mir nicht anders zu helfen.

An der markierten Stelle erscheint die Warnung, und ich weiß nicht, warum. Es wäre sehr nett, wenn sich jemand die Mühe macht und sich da reindenkt.

Vielen Dank!

Beste Grüße

  1. Hallo nochmal,

    public function getPostings() {
            return array(
                "20060715t1m1rel0" => "Ausgangsposting",
                "20060715t1m2rel1m1" => "Erste Antwort auf das Ausgangsposting",
                "20060715t1m3rel1m1" => "Zweite Antwort auf das OP",
                "20060715t1m4rel2m3" => "Antwort auf Zweite Antwort"
            );
        }

    Wie gesagt, erstmal nur Testhalber, daher werden die Postings eines Threads durch ein simples Array repräsentiert.

    Beste Grüße

    1. Hallo Richard,

      Was kommt heraus, wenn du an der Problemstelle
      print_r($this->getChildren( $mid ));
      einfuegst?

      Gruß,

      Dieter

  2. Hallo Richard,

    ich programmieren gerade ein einfaches threadbasiertes Forum.

    mein Posting hilft Dir nicht bei Deinem aktuellen Problem, vielleicht hilft es Dir aber, einen neuen Zugang zu Deiner Aufgabenstellung zu finden.

    In einem threadbasierten Forum liegen die Postings in einer Baumstruktur vor. Daher solltest Du meiner Meinung nach zunächst die dazu passende Datenstruktur implementieren. Dein Ansatz irgendwie mit RegExps Kinder zu finden, ist meiner Meinung nach schauderhaft und hat mit den Vorzügen objektorientierter Programmierung nichts zu tun.

    Ideen: Ein Posting ist ein Objekt. Eigenschaften dieses Objektes könnten beispielsweise

    - Autor
       - Datum/Zeit
       - Thema
       - Inhalt (gaanz wichtig)

    sein, aber auch

    - Vorgängerposting (kann vorhanden sein. Ist es nicht vorhanden, so
                           handelt es sich um das Startposting eines neuen
                           Threads)
                           Elterobjekt in einem Baum
       - Liste der Antwortpostings (und damit der Kinder)

    Implementiere zunächst eine Baumstruktur - und Algorithmen zum Durchlaufen einer Baumstruktur. Die gibt es, sogar fertig. Dann erst fülle die Knoten und Blätter (sprich Postings) mit Inhalt, d.h. erweitere Dein Objekt um die Nutzlast.

    Freundliche Grüße

    Vinzenz

  3. hallo,

    Das funktioniert soweit auch alles wunderbar, nur bekomme ich nach jedem Posting die im Titel angegebene Warnung "Warning: Invalid argument supplied for foreach() in C:\web\Apache2\htdocs\OOP\class.php on line 11".

    Dann funktioniert es eben doch nicht.

    Ich bin mir nicht sicher, was nun Zeile 11 ist, aber ich vermute, es geht um diese Zeile:

    foreach( $this->getPostings() as $mid => $posting ) {

    getPostings() sollte ein Array sein, der von einer "public"-Funktion erzeugt wird, du willst ihn aber in einer "private"-Funktion verwenden. Dazu nimmst du $this(). "$this()->methodenname" müßte auf eine Methode des aktuellen Objekts zugreifen. "Die Pseudovariable $this ist verfügbar, falls eine Methode aus einem Objektkontext heraus aufgerufen wird. $this ist eine Referenz auf das aufrufende Objekt (üblicherweise das Objekt zu dem die Methode gehört, es kann sich aber auch um ein anderes Objekt handeln, falls die Methode statisch aus dem Kontext eines zusätzlichen Objektes aufgerufen wird)" kannst du im Handbuch nachlesen. Ich vermute, daß das der angemerkte Fehler ist.
    Dann mach es einfach folgendermaßen:
        foreach( Thread::getPostings() as $mid => $posting ) {
    Mehr als schiefgehen kanns ja nicht.

    Grüße aus Berlin

    Christoph S.

    --
    Visitenkarte
    ss:| zu:) ls:& fo:) va:) sh:| rl:|
  4. Moin!

    ich programmieren gerade ein einfaches threadbasiertes Forum.

    Und das machst du in meinen Augen gar nicht gut.

    Hauptkritikpunkt an deinem sichtbaren Code ist: Du mischst Darstellung (in Form von HTML-Codefragmenten, die darüber hinaus noch mit Inline-CSS verseucht sind) und Datenhaltung.

    Wenn ich mein bislang gesammeltes OOP-Wissen zum Besten geben darf: Erstelle eine Klasse, die ein Posting darstellt. Erstelle eine Klasse, die einen ganzen Threadbaum aus Postings darstellt. Und erstelle eine Klasse, der du ein Threadobjekt übergibst, und die daraus eine HTML-Ausgabe macht - templatebasiert, wenn's geht.

    Anforderungsabhängig gibts da ja durchaus auch Varianten, die Ausgabe mit einem Standardinterface zu betreiben, die konkrete Umsetzung (HTML, Text, RSS, Atom etc.) aber durch eine Factory kontextabhängig zu realisieren.

    Ansonsten:

    /* HIER KOMMT DIE WARNUNG */
                foreach( $this->getChildren( $mid ) as $child ) {
                    $this->drawThread( $child );
                }

    Offenbar willst du von der Methode $this->getChildren() ein Array zurückerhalten.  
      
    Wo passiert das denn?  
      
    
    > ~~~php
      
    
    >     private function getChildren( $mid ) {  
    >         $children = array();  
    >         $RE_getMessageRelation = "/[0-9]{8}t[0-9]+m([0-9])+rel[0-9]+m[0-9]+/";  
    >         $RE_getRelated = "/[0-9]{8}t[0-9]+m[0-9]+rel[0-9]+m([0-9])+/";  
    >         preg_match( $RE_getMessageRelation, $mid, $messageNumber );  
    >         foreach( $this->getPostings() as $mid => $posting ) {  
    >             preg_match( $RE_getRelated, $mid, $relationNumber );  
    >             if( ( $relationNumber && $messageNumber ) ) {  
    >                 if( $relationNumber[1] == $messageNumber[1] ) {  
    >                     $children[$mid] = $posting;  
    >                 }  
    >             }  
    >         }  
    >     }
    
    

    Ein return habe ich in dem Code jedenfalls nicht gefunden.

    Abgesehen davon halte ich es für extrem schlecht programmiert, bei jedem Aufruf eines Threads massenhaft RegEx zu durchlaufen. Wie andernorts schon erwähnt: Speicher deine Postings in einer GEEIGNETEN Struktur. Ein eindimensionales, durch Textschlüssel verdrahtetes Array ist keine geeignete Struktur für einen Threadbaum.

    - Sven Rautenberg

    --
    "Love your nation - respect the others."
  5. Hallo an Alle,

    ich wollte jetzt nicht jedem einzeln antworten.

    1. Sven, du hast natürlich recht, da fehlt ein return. *mir vor den Kopf stoß*
    2. Sven, Christoph und Vinzenz, ihr habt natürlich recht, dass die Datenstruktur schlecht ist. Aber dessen war ich mir von Anfang an bewusst. Ich wollte an einzelnen Punkten testen, um für bestimmte Aufgaben geeignete Algorithmen zu finden. Dazu gehörte erstmal _nur_ das Zeichnen des Threadbaums.

    Möglicherweise habt ihr meinen Nachtrag überlesen oder ich habe mich nicht deutlich genug ausgedrückt. Das ganze war bis jetzt nicht praxistauglich, aber darum ging es erstmal auch gar nicht. Da mir aber noch Erfahrungen fehlen (ich lerne PHP erst seit wenigen Monaten), wollte ich eben erstmal rumprobieren.

    Beste Grüße

    1. Hallo Richard,

      1. Sven, Christoph und Vinzenz, ihr habt natürlich recht, dass die Datenstruktur schlecht ist. Aber dessen war ich mir von Anfang an bewusst. Ich wollte an einzelnen Punkten testen, um für bestimmte Aufgaben geeignete Algorithmen zu finden. Dazu gehörte erstmal _nur_ das Zeichnen des Threadbaums.

      leider kannst Du diese zwei Dinge nicht trennen :-)

      Wie willst Du mit einer ungeeigneten Struktur einen geeigneten Algorithmus für die geeignete Struktur ermitteln? Das ist mir völlig schleierhaft.

      Baumstruktur und Durchlaufen einer Baumstruktur gehören zusammen. Sinnvolles Durchlaufen einer Baumstruktur basiert auf einem Algorithmus, der auf einer Baumstruktur arbeitet. Wie Du diese Baumstruktur realisierst, das ist eine ganz andere Geschichte. Und das Zeichnen eines einzelnen Threads basiert auf dem Durchlaufen des zugehörigen Baumes von der Wurzel, dem Ausgangsposting, bis hin zu den Blättern, d.h. Antwortpostings, auf die noch niemand geantwortet hat.

      Als Lesetipp möchte ich Dir die entsprechenden Artikel aus der englischsprachigen Wikipedia Tree, data structure und tree traversal ans Herz legen, die deutsche Wikipedia ist hier überraschenderweise wenig informativ. Es lohnt sich nicht wirklich, Baum (Graphentheorie) und verlinkte Artikel zu lesen. Ich habe zumindest nichts Vernünftiges über das Durchlaufen von Bäumen gefunden. :-(

      Möglicherweise habt ihr meinen Nachtrag überlesen

      Doch, doch. Dieses Posting habe ich schon durchgelesen. Es bestätigte mich darin, Dir zu raten, mit einem ganz neuen Ansatz an Deine Aufgabenstellung heranzugehen.

      oder ich habe mich nicht deutlich genug ausgedrückt. Das ganze war bis jetzt nicht praxistauglich, aber darum ging es erstmal auch gar nicht. Da mir aber noch Erfahrungen fehlen (ich lerne PHP erst seit wenigen Monaten), wollte ich eben erstmal rumprobieren.

      Richard, es ist völlig gleichgültig, in welcher Programmiersprache Du Dein Übungsobjekt "threadbasiertes Forum" umsetzen willst. Die Datenstrukturen, Algorithmen und Objekte bleiben die gleichen.

      Wenn Du Deine Objekte sauber definiert hast, die geeigneten Algorithmen für die notwendigen Datenstrukturen gefunden hast, dann kannst Du das Konzept in den verschiedensten Sprachen umsetzen. Die Programmiersprachen stellen Dir zwar unterschiedliche Werkzeuge zur Verfügung, haben eine unterschiedliche Syntax, der Lösungsweg wird bei sehr vielen Programmiersprachen sehr ähnlich ausfallen.

      Genau aus diesem Grund solltest Du die Problemstellung, die Du Dir selbst gestellt hast, richtig[tm] angehen - und nicht Zeit und Mühe mit abstrusen Experimenten vergeuden. Grundlegender Umgang mit Datenstrukturen und Algorithmen mag Dir langweilig vorkommen, solide Kenntnisse derselben helfen Dir jedoch später bei konkreten Problemen.

      Ich kann Dir als Lektüre ein Standardwerk zu Algorithmen empfehlen:

      Robert Sedgewick, Algorithmen (Addison-Wesley)

      Das Buch gibt es in verschiedenen Versionen für verschiedene Programmiersprachen. Mir hat es seinerzeit wenig ausgemacht, dass meine Ausgabe "Algorithmen in Pascal" ist, während ich die Algorithmen und Datenstrukturen in C umsetzte - ganz im Gegenteil, ich habe so noch mehr gelernt. Vielleicht kannst Du ein Exemplar über die Bibliothek Deiner Wahl ausleihen.

      Freundliche Grüße

      Vinzenz

      1. Hallo Vinzenz,

        leider kannst Du diese zwei Dinge nicht trennen :-)

        In diesem Falle schon: die drawThread-Methode würde sich durch Verbessern der Datenstruktur im Kern nicht verändern.

        Wie willst Du mit einer ungeeigneten Struktur einen geeigneten Algorithmus für die geeignete Struktur ermitteln? Das ist mir völlig schleierhaft.

        :-)

        Als Lesetipp möchte ich Dir die entsprechenden Artikel aus der englischsprachigen Wikipedia Tree, data structure und tree traversal ans Herz legen

        Uff, für englisch ist es heute schon ein bisschen spät, aber ich werde mir das bei Gelegenheit mal anschauen.

        oder ich habe mich nicht deutlich genug ausgedrückt. Das ganze war bis jetzt nicht praxistauglich, aber darum ging es erstmal auch gar nicht. Da mir aber noch Erfahrungen fehlen (ich lerne PHP erst seit wenigen Monaten), wollte ich eben erstmal rumprobieren.

        Richard, es ist völlig gleichgültig, in welcher Programmiersprache Du Dein Übungsobjekt "threadbasiertes Forum" umsetzen willst. Die Datenstrukturen, Algorithmen und Objekte bleiben die gleichen.

        OK, dann tausche ich hiermit das Wort "PHP" durch "Programmierung" aus, das bisschen Excel-VBA was ich davor schon gemacht habe, lasse ich mal außen vor. Ansonsten hat der Satz aber seine Gültigkeit.

        Grundlegender Umgang mit Datenstrukturen und Algorithmen mag Dir langweilig vorkommen, solide Kenntnisse derselben helfen Dir jedoch später bei konkreten Problemen.

        Das möchte ich so nicht auf mir sitzen lassen. Wenn dem so wäre, hätte ich diese "abstrusen Experimente" gar nicht erst durchgeführt. Mag sein, dass mir die gegenseitige Bedingung von Datenstruktur und Algorithmus nicht vollständig klar war, aber wie sollte ich das lernen, wenn nicht durch eigene (ruhig auch mal negative) Erfahrungen?

        Ich kann Dir als Lektüre ein Standardwerk zu Algorithmen empfehlen:

        Robert Sedgewick, Algorithmen (Addison-Wesley)

        Das Buch gibt es in verschiedenen Versionen für verschiedene Programmiersprachen. Mir hat es seinerzeit wenig ausgemacht, dass meine Ausgabe "Algorithmen in Pascal" ist, während ich die Algorithmen und Datenstrukturen in C umsetzte - ganz im Gegenteil, ich habe so noch mehr gelernt. Vielleicht kannst Du ein Exemplar über die Bibliothek Deiner Wahl ausleihen.

        Ich werde mich demnächst mal umschauen, vielen Dank für den Tipp.

        Beste Grüße