Display a nested array in a branch

Here is my message object. This is a class that defines messages between users in my application.

class Message { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @var string * @Assert\NotBlank(message="private_message.title.blank") * @ORM\Column(name="title", type="string", length=50) */ protected $title; /** * @Assert\NotBlank(message="private_message.receiver.blank") * @ORM\ManyToOne(targetEntity="MedAppBundle\Entity\User") * @ORM\JoinColumn(referencedColumnName="id") */ protected $receiver; /** * @ORM\ManyToOne(targetEntity="MedAppBundle\Entity\User") * @ORM\JoinColumn(referencedColumnName="id") */ protected $sender; /** * @var string * @Assert\NotBlank(message="private_message.content.blank") * @ORM\Column(name="content", type="string") */ protected $content; /** * @var \DateTime * * @ORM\Column(name="sentAt", type="datetime") */ protected $sentAt; /** * @var boolean * * @ORM\Column(name="isSpam", type="boolean") */ protected $isSpam = false; /** * @var \DateTime * * @ORM\Column(name="seenAt", type="datetime",nullable=true) */ protected $seenAt = null; /** * @ORM\ManyToOne(targetEntity="PrivateMessageBundle\Entity\Message") * @ORM\JoinColumn(referencedColumnName="id",nullable=true) */ protected $replyof; /** * @ORM\OneToMany(targetEntity="PrivateMessageBundle\Entity\Message", mappedBy="replyof") **/ private $replies; public function __construct() { $this->replies = new ArrayCollection(); } 

It is important to note the replyof variable, which tells which message is the parent of the message. If it is NULL, the message is not a response, it is the parent message (root).

And the messages variable, which is an array of messages that respond to a message. These answers may have the answers themselves. This array can also be NULL for leaf nodes because they have no answer.

All other variables contain only some fields that define the actual message between two users.

What I'm trying to do is show in Twig all my dungeon messages, for example:

 message1 - root message, reply of none, but has replies reply1 - first reply of message 1 reply1 first reply of reply 1 of message 1, leaf with no further replies reply2 - second reply of message 1, leaf with no further replies message2 - root message, no replies and a reply of none 

The problem is that Twig only supports foreach loops, and I'm not sure how to display this format when it has a higher depth, more than two.

 {% for reply in message.replies %} <li> sent by: {{ reply.sender }} </li> <li> title: {{ reply.title }} </li> <li> content: {{ reply.content }} </li> <li> date: {{ reply.sentAt|date('dmY H:i:s') }} </li> <hr> {% endfor %} 

Each message reply will be displayed, but how can I display the attached messages to the full depth?

+5
source share
2 answers

I have not tested it, you should be able to iterate over the answers:

 {% for reply in message.replies %} {% if loop.first %}<ul>{% endif %} <li> sent by: {{ reply.sender }} </li> <li> title: {{ reply.title }} </li> <li> content: {{ reply.content }} </li> <li> date: {{ reply.sentAt|date('dmY H:i:s') }} </li> {% for reply in reply.replies %} {% if loop.first %}<li><ul>{% endif %} <li> sent by: {{ reply.sender }} </li> <li> title: {{ reply.title }} </li> <li> content: {{ reply.content }} </li> <li> date: {{ reply.sentAt|date('dmY H:i:s') }} </li> {% if loop.last %}</ul></li>{% endif %} {% endfor %} {% if loop.last %}</ul>{% endif %} {% endfor %} 

It displays only 2 levels of answers. You can use Twig macro to define a reusable function that should display answers recursively:

 {# define the macro #} {% macro displayReply(reply) %} <li> sent by: {{ reply.sender }} </li> <li> title: {{ reply.title }} </li> <li> content: {{ reply.content }} </li> <li> date: {{ reply.sentAt|date('dmY H:i:s') }} </li> {% for reply in reply.replies %} {% if loop.first %}<li><ul>{% endif %} {{ displayReply(reply) }} {% if loop.last %}</ul></li>{% endif %} {% endfor %} {% endmacro %} {# use the macro #} {% for reply in message.replies %} {% if loop.first %}<ul>{% endif %} {{ displayReply(reply) }} {% if loop.last %}</ul>{% endif %} {% endfor %} 

Depending on your request, it may display the answers in the wrong order; you may need to sort the answers in descending order in your request.

+2
source

You can do a recursive approach as follows:

in the main branch, you print the main message and repeat recursively in partial order:

 ## main twig Root message: <ul> <li> sent by: {{ message.sender }} </li> <li> title: {{ message.title }} </li> <li> content: {{ message.content }} </li> <li> date: {{ message.sentAt|date('dmY H:i:s') }} </li> {{ include('AcmeDemoBundle:Message:_elem.html.twig', {'replies': message.replies ) }} </ul> 

and

 ## AcmeDemoBundle:Message:_elem.html.twig <ul> {% for reply in replies %} <li> sent by: {{ reply.sender }} </li> <li> title: {{ reply.title }} </li> <li> content: {{ reply.content }} </li> <li> date: {{ reply.sentAt|date('dmY H:i:s') }} </li> {{ include('AcmeDemoBundle:Message:_elem.html.twig', {'replies': reply.replies ) }} {% endfor %} </ul> 

hope this help

+1
source

All Articles