Bonjour,

Je suis actuellement en train de suivre le tutoriel sur les commentaires imbriqués. Seulement, je n'utilise pas le framework Slim mais Laravel (5.4).

Ce que je fais

Dans mon controller ArticleController.php et dans la méthode show($id) me permettant d'afficher un article en fonction de l'id, je fais ceci :

public function show($id)
    {
        $article  = Article::online()->findOrFail($id);
        $comments = $comments_by_id = $this->findAllById($post_id);

        foreach ($comments as $id => $comment) {
            if ($comment->parent_id != 0) {
                $comments_by_id[$comment->parent_id]->children[] = $comment;

                if ($unset_children) {
                    unset($comments[$id]);
                }
            }
        }

        return view('articles.show', compact('article', 'comments'));
    }

On appelle une fonction findAllById() pour récupérer tous les commentaires :

public function findAllById($id)
    {
        $comments = Comment::get()->where('article_id', $id)->toArray();

        // Dans le tuto, on faisait ceci, je l'ai adapté pour laravel.

        // $req = $this->pdo->prepare('SELECT * FROM comments WHERE post_id = ?');
        // $req->execute([$post_id]);
        // $comments = $req->fetchAll();

        $comments_by_id = [];

        foreach ($comments as $comment) {
            $comments_by_id[$comment->id] = $comment;
        }

        return $comments_by_id;
    }

Ma table comments a pour colonne : id, article_id, user_id, parent_id, content, created_at, updated_at. Pour l'imbrication des commentaires, on utilise parent_id qui correspond à l'id d'un autre commentaire.

Ce que j'obtiens

Seulement, j'obtiens cette erreur : Indirect modification of overloaded property App\Models\Comment::$children has no effect. Le problème vient de cette ligne de code :

$comments_by_id[$comment->parent_id]->children[] = $comment;

Alors j'ai cherché sur internet et y a tout et n'importe quoi. Certains parlent de modifier la surchage magique get() par & get() (l'espace est fait exprès, markdown le prend en compte sinon). D'autres disent que c'est le push sur l'objet qui pose un soucis. Et un autre tente d'expliquer, mais je n'ai pas compris comment le mettre en application à mon code.

Alors je m'en remets à vous, saurez vous pourquoi je ne peux pas ajouter une dimension au tableau nommé children ? Pourtant je travaille bien sur un tableau grâce à toArray() lors de la récupération de tous mes commentaires.

1 réponse


JeremyB
Auteur
Réponse acceptée

Bon, j'ai réussi à avoir le bon résultat en modifiant ainsi (ArticleController.php) :

<?php
public function show($id, $unset_children = true)
    {
        $article  = Article::online()->findOrFail($id);
        $comments = $this->findAllComments($id);

        foreach ($comments as $id => $comment) {
            if ($comment['parent_id'] != 0) {
                $comments[$comment['parent_id']]['children'][] = $comment;

                if ($unset_children) {
                    unset($comments[$id]);
                }
            }
        }

        return view('articles.show', compact('article', 'comments'));
    }

    public function findAllComments($id)
    {
        $comments = Comment::with([
            'user' => function ($query) {
                $query->select('id', 'name');
            }
        ])->where('article_id', $id)->get()->toArray();

        $comments_by_id = [];

        foreach ($comments as $comment) {
            $comments_by_id[$comment['id']] = $comment;
        }

        return $comments_by_id;
    }

Ma vue donne ceci (/views/articles/show.blade.php) :

<?php
@foreach ($comments as $key => $comment)
            @include('comments.comment')
        @endforeach

L'include contient ceci :

<div class="panel panel-default" id="comment-{{ $comment['id'] }}">
    <div class="panel-body">
        <p>{{$comment['content']}}</p>

        @if ($comment['parent_id'] < 1)
            <p class="text-right">
                {{-- <= $app->urlFor('comments.delete', ['id' => $comment['id']]); ?> --}}
                <a href="#" class="btn btn-danger">
                    Supprimer
                </a>
                <button class="btn btn-default reply" data-id="{{ $comment['id'] }}">
                    Répondre
                </button>
            </p>
        @endif
    </div>
</div>

<div style="margin-left: 50px;">
    @if (isset($comment['children']))
        @foreach ($comment['children'] as $comment)
            @include('comments.comment')
        @endforeach
    @endif
</div>

Voilà, si ça peut aider celui qui souhaite avoir des commentaires imbriqués sur Laravel (version 5.4.32 pour moi).