ITnetwork Flashka zdarma C# týden
Akce! Pouze tento týden sleva až 80 % na kurzy C# .NET. Lze kombinovat s akcí 50 % bodů navíc na prémiový obsah!
Brno? Vypsali jsme pro vás nové termíny školení Základů programování a OOP v Brně!

Diskuze: Komentáře a odpovědi výpis ke článku

Aktivity (1)
Avatar
jAk3r
Člen
Avatar
jAk3r:16.10.2018 9:23

Čau,

dělám si komentáře ke článkům a vše mi funguje ale narazil jsem na to že nemám absolutně nápad jak udělat výpis komentářů a odpovědi k daným komentářům.

Představoval bych si to něco jako:

Foreach na komentáře a v něm vnořený další foreach na odpovědi.

Můj aktuální pokus

public function getComments($article_id, $parent_id = null){
            $comments = null;

            if ($parent_id === null) {
            $comments = $this->database->table(self::TABLE_COMMENTS)->where(self::COLUMN_COM_ARTICLE_ID, $article_id)->order('created_at')->fetchAll();
        } else {
            $comments = $this->database->table(self::TABLE_COMMENTS)->where(self::COLUMN_COM_ARTICLE_ID ,$article_id)->where(self::COLUMN_COM_PARENT_ID, $parent_id)->fetchAll();
        }

        $_comments = [];

            foreach ($comments as $comm) {
            // zpracování komentáře
            $_comment = [
                'comment_id' => $comm->comment_id,
                'user_id' => $comm->user_id,
                'created_at' => $comm->created_at,
                'content' => $comm->content,
            ];
        }

        if ($parent_id === null) { // pokud je to hlacní komentář zjistit pod-komentáře
            $_comment['comments'] = $this->getComments($article_id, $parent_id);
        }

        $_comments[] = $_comment;


        return $_comments; // vrátit komentáře

    }

Ale to mi háže : Maximum function nesting level of '256' reached, aborting!

Tudíž tam mám nějaké blbé zacyklení...

Tady mám starý kód

$pocetKomentaru = 0;

function processComments($clanek_id, $parent_id = NULL) {
    global $pocetKomentaru;
    $komentare = NULL;

    if ($parent_id === NULL) {
        $komentare = dibi::query("
                SELECT k.*, a.nick, a.avatar FROM komentare k
                LEFT JOIN accounts a ON k.author_id = a.id
                WHERE k.clanek_id = %i AND k.parent_id IS NULL", $clanek_id);
    } else {
        $komentare = dibi::query("
                SELECT k.*, a.nick, a.avatar FROM komentare k
                LEFT JOIN accounts a ON k.author_id = a.id
                WHERE k.clanek_id = %i AND k.parent_id
                ", $clanek_id, " = %i", $parent_id);
    }

    $_komentare = [];

    foreach ($komentare as $komentar) {
        // zpracování komentáře
        $_komentar = [
            'id' => $komentar->id,
            'avatar' => $komentar->avatar,
            'komentar' => $komentar->komentar,
            'pridano' => $komentar->pridano,
            'nick' => $komentar->nick,
        ];

        if ($parent_id === NULL) { // pokud je to hlacní komentář zjistit pod-komentáře
            $_komentar['komentare'] = processComments($clanek_id, $komentar->id);
        }

        $pocetKomentaru++;
        $_komentare[] = $_komentar; // přidat zpracovaný komentář do pole komentářů
    }

    return $_komentare; // vrátit komentáře
}

Zde také přikládám šablonu jak by to mělo fungovat

{snippet comments}
                      <div n:foreach="$comments as $comment" class="media">
                          <a class="media-left" href="#">
                              <img src="{$basePath}/images/user/avatar3.jpg" alt="" />
                          </a>
                          <div class="media-body">
                              <div class="media-content">
                                  <a href="#" class="media-heading"></a>
                                  <a n:if="$user->isLoggedIn()" n:href="reply! $comment['comment_id']" id="reply" class="btn btn-sm btn-primary pull-right ajax">reply</a>
                                  <span class="date">{$comment['created_at']|date:'j. n. Y H.i'}</span>
                                  <p>{$comment['content']}</p>
                              </div>

                              <div n:foreach="$comment['comments'] as $comm" class="media">
                                  <a class="media-left" href="#">
                                      <img src="{$basePath}/images/user/avatar.jpg" alt="" />
                                  </a>
                                  <div class="media-body">
                                      <div class="media-content">
                                          <a href="#" class="media-heading">YAKUZI</a>
                                          <a href="#" class="btn btn-sm btn-primary pull-right">reply</a>
                                          <span class="date">{$comm['created_at']|date:'j. n. Y H.i'}</span>
                                          <p>{$comm['content']}</p></div>
                                  </div>
                              </div>
                          </div>
                      </div>
                  {/snippet}

Představoval bych si to jako hlavní foreach v tomto případě $comments a v něm v nořený další foreach na případné odpovědi ale absolutně nechápu jak na to..

Díky všem za pomoc a radu :)

Editováno 16.10.2018 9:24
Odpovědět 16.10.2018 9:23
Pokud něčeho chceš dosáhnout, musíš si za tím jít.
Avatar
dez1nd
Člen
Avatar
dez1nd:16.10.2018 12:49

Ahoj, koukám na to a hned asi vidím problém.

ve funkci processComments() se neustále odkazuješ na sebe. Odkrokuj si co se stane když zavoláš funci proccesComments(1); Dle mě ta funkce jede stále dokola a nemůže přestat protože jí stále předáváš druhej parametr jako null a tím pádem se zavolá znova se stejným paremetrem a tak pořád dokola a dokola dokud nespadne, protože nemůžeš mít nekonečné pole.

 
Nahoru Odpovědět 16.10.2018 12:49
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na jAk3r
Daniel Vítek:16.10.2018 13:13

No především ve funkci getComments provádíš tento kód:

if ($parent_id === null) { // pokud je to hlacní komentář zjistit pod-komentáře
            $_comment['comments'] = $this->getComments($article_id, $parent_id);
        }

        $_comments[] = $_comment;

až za foreachem, takže ti do $_comments spadne jen poslední $_comment.

Teoreticky by tohle všechno mělo jít udělat přímo v pohledu. Pokud máš správně nastavený cizí klíč, stačí, když vezmeš hlavní komentáře, a na každý podkomentář rekurzivně zavoláš ->related

https://doc.nette.org/…ase-explorer

Nahoru Odpovědět  +1 16.10.2018 13:13
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
jAk3r
Člen
Avatar
Odpovídá na Daniel Vítek
jAk3r:16.10.2018 13:25

Ale já mám ty komentáře i odpovědi ve stejné tabulce... to nevadí?

Nahoru Odpovědět  -1 16.10.2018 13:25
Pokud něčeho chceš dosáhnout, musíš si za tím jít.
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na jAk3r
Daniel Vítek:16.10.2018 13:29

Kdyby sis to zkusil, zjistil bys, že nevadí :)

Nahoru Odpovědět  ±0 16.10.2018 13:29
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
jAk3r
Člen
Avatar
Odpovídá na Daniel Vítek
jAk3r:16.10.2018 13:32

Takže takto?

public function getComments($article_id, $parent_id = null, &$_comments = [])
{
    $comments = $this->database->table(self::TABLE_COMMENTS)->where(self::COLUMN_COM_ARTICLE_ID, $article_id)->order('created_at')->fetchAll();

    foreach ($comments->related('parent_id') as $comm) {
        // zpracování komentáře
        $_comment = [
            'comment_id' => $comm->comment_id,
            'user_id' => $comm->user_id,
            'created_at' => $comm->created_at,
            'content' => $comm->content,
        ];

       /* if ($comm->parent_id !== null) {
            $_comment['comments'] = $this->getComments($article_id, $comm->parent_id, $_comments);
        }*/

        $_comments[] = $_comment;
    }

    return $_comments; // vrátit komentáře
}
Nahoru Odpovědět  -2 16.10.2018 13:32
Pokud něčeho chceš dosáhnout, musíš si za tím jít.
Avatar
Peter Mlich
Člen
Avatar
Peter Mlich:16.10.2018 16:05

Vsechny ty komentare by meli mit v tabulce jeden sloupec s id toho clanku. A potom dalsi sloupec, ve kterem je id komentare, na ktery navazuji. Cili, z databaze seznam komentaru vytahnes jako jednu tabulku. Dal uz pak zalezi jen na tom, jak si je usporadas. To by melo byt soucasti sql prikazu. Ale klidne to muzes delat az v php nebo v js.

Stejne, nejlepsi system je mit komentare serazene podle data a pridat tam link, na ktery komentar to navazuje. Jako, muj nazor z pohledu ctenare. Podle kontextu obvykle dokazi i bez jmena si tipnout k cemu je to reakce. Ale kdyz nekdo zareaguje uprostred text, to si nevsimnes.
Jako, stromova struktura je pekna. Ale kdyz to jde, prepinam na serazeni podle datumu.

 
Nahoru Odpovědět 16.10.2018 16:05
Avatar
jAk3r
Člen
Avatar
Odpovídá na Daniel Vítek
jAk3r:22.10.2018 9:48

Nějak takto si to myslel? Ale nefunguje to úplně jak bych chtěl...

  1. Chci aby články co jsou parrent=null jsou jako hlavní.
  2. 2 foreach kde se budou vypisovat pod hlavní komentáře odpovědi.
    public function getComments($article_id){

        $comments = $this->database->table(self::TABLE_COMMENTS)->where(self::COLUMN_COM_ARTICLE_ID, $article_id)->order('created_at')->fetchAll();

    foreach ($comments as $comment) {
        // zpracování komentáře
        $_comments = [
            'comment_id' => $comment->comment_id,
            'user_id' => $comment->user_id,
            'created_at' => $comment->created_at,
            'content' => $comment->content,
        ];
        foreach ($comment->related('comments.parent_id') as $com) {
            $_comment['comments'] = [
                'comment_id' => $com->comment_id,
                'user_id' => $com->user_id,
                'created_at' => $com->created_at,
                'content' => $com->content,
            ];
        }
    }

    $_comments[] = $_comment;

    return $_comments; // vrátit komentáře

}
Akceptované řešení
+5 Zkušeností
Řešení problému
Nahoru Odpovědět 22.10.2018 9:48
Pokud něčeho chceš dosáhnout, musíš si za tím jít.
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na jAk3r
Daniel Vítek:22.10.2018 12:24

Defakto ano, jen s tím rozdílem, že to budeš muset rekurzivně zanořit (pokud chceš mít neomezeně úrovní). A můžeš to dělat rovnou v lattečku.

Nahoru Odpovědět 22.10.2018 12:24
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.