2015-09-17 14 views
9

Tôi có gói/thực thể thư riêng cho phép người dùng gửi thư giữa chúng.Thêm trường văn bản biểu mẫu trả lời cho từng thư đã nhận

lĩnh vực của nó là như sau:

/** 
* @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") 
* @AcmeAssert\IsHimself(message="private_message.receiver.himself", groups={"new"}) 
* @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",inversedBy="replies") 
* @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(); 
} 

Thông báo lĩnh vực replyof, nó tham chiếu đến message khác, và replies một tham chiếu đến một loạt các messages. Nếu replyof là không, thì thư không phải là thư trả lời của bất kỳ thư nào.

Tôi có mẫu ghép với macro hiển thị thông báo của người dùng và tất cả các thư trả lời của thư đó. Những gì tôi muốn làm là có một textfield trả lời theo mỗi trong số này, chính xác như Gmail, cho phép tôi thêm một trả lời cho mỗi thư.

Nhưng khi tôi thêm nó vào mẫu, chỉ có một được hiển thị bởi vì nó có một Id duy nhất. Làm cách nào để thêm biểu mẫu trả lời sau mỗi câu trả lời? FormType của họ sẽ trông như thế nào?

Đây cũng là mẫu cành lá của tôi:

{% macro displayReply(reply,replyform) %} 
     {% import _self as macros %} 


     {# <li> id: {{ reply.id }} </li> 
     <li> sent by: {{ reply.sender }} </li> 
     <li> title: {{ reply.title }} </li> 
     <li> content: {{ reply.content }} </li> 
     <li> date: {{ reply.sentAt|date('d-m-Y H:i:s') }} </li> 
     <a href="{{ path('private_message_new',{'msg':reply.id}) }}"> reply </a> 
     <hr> #} 
     <div class="panel panel-default"> 
      <div class="panel-body"> 
       <div class="message-info"> 
        <input type="hidden" name="messageid" id="messageId" value="{{ reply.id }}"> 

        <div class="message-title clearfix"> 
         <h4 class="pull-left">{{ reply.title }}</h4> 
        </div> 
        <hr class="lite-line"> 
        <div class="message-sender clearfix"> 
         <div class="pull-left sender"> 
          {{ reply.sender }} 
         </div> 
         <div class="pull-right"> 
          to <b>{{ (reply.receiver==app.user)?'me':reply.receiver }}</b> on <span 
            class="message-timestamp">{{ reply.sentAt|date('F d, Y H:i:s') }}</span> 
          <a class="btn btn-start-order" role="button" 
           href="{{ path('private_message_new',{'msg':reply.id}) }}">Reply</a> 
         </div> 

        </div> 
        <hr class="lite-line"> 
        <div class="message-box clearfix"> 
         <span>{{ reply.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span> 
        </div> 

        {{ form_start(replyform) }} 
        <input type="submit"> 
        {{ form_end(replyform) }} 

       </div> 
      </div> 
     </div> 
     {% for reply in reply.replies %} 

      {% if loop.first %}<div>{% endif %} 
      {{ macros.displayReply(reply) }} 
      {% if loop.last %}</div>{% endif %} 

     {% endfor %} 
    {% endmacro %} 

    {% import _self as macros %} 
    {# use the macro #} 

    <div class="message-back"> 
     <a class="btn btn-start-order-dark btn-block" role="button" 
      href="{{ path('private_message',{'page':'inbox'}) }}"> 
      <span class="fa fa-undo"></span> Go back 
     </a> 
    </div> 

    <div class="messages"> 
     <div class="panel panel-default"> 
      <div class="panel-body"> 
       <div class="message-info"> 
        <input type="hidden" name="messageid" id="messageId" value="{{ message.id }}"> 

        <div class="message-title clearfix"> 
         <h4 class="pull-left">{{ message.title }}</h4> 
        </div> 
        <hr class="lite-line"> 
        <div class="message-sender clearfix"> 
         <div class="pull-left sender"> 
          {{ message.sender }} 
         </div> 
         <div class="pull-right"> 
          to <b>{{ (message.receiver==app.user)?'me':message.receiver }}</b> on <span 
            class="message-timestamp">{{ message.sentAt|date('F d, Y H:i:s') }}</span> <a 
            class="btn btn-start-order" role="button" 
            href="{{ path('private_message_new',{'msg':message.id}) }}">Reply</a> 
         </div> 
        </div> 
        <hr class="lite-line"> 
        <div class="message-box clearfix"> 
         <span>{{ message.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span> 
        </div> 

        {{ form_start(replyform) }} 
        <input type="submit"> 
        {{ form_end(replyform) }} 
       </div> 
      </div> 
     </div> 
    </div> 
    {% for reply in message.replies %} 

     {% if loop.first %}<div class="replies">{% endif %} 
     {{ macros.displayReply(reply ,replyform) }} 
     {% if loop.last %}</div>{% endif %} 
    {% endfor %} 

ý rằng tôi lần đầu tiên hiển thị các tin nhắn, sau đó áp dụng các macro để nó hiển thị tất cả trả lời của nó như là một cái cây. Nó cũng sẽ hiển thị các câu trả lời của bài trả lời, theo cách đệ quy, cho đến khi các nút lá. Tôi thêm một 'trả lời' sau mỗi, nhưng tôi không chắc chắn như thế nào FormType nên được.

Loại biểu mẫu trả lời của tôi giống như thế này, nhưng tôi chắc chắn nó sai.

public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder 
     ->add('title') 
     ->add('content', 'textarea') 
     ; 

} 

Đối với các trường khác của thư trả lời, tôi quản lý chúng trong bộ điều khiển. Tôi nghĩ rằng tôi nên làm điều này sau khi nhận được tin nhắn từ hình thức mặc dù. Một cái gì đó như thế này, và có được tiêu đề, nội dung và replyof từ formdata.

$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message'); 
    $isforme = $messages->findOneBy(array('receiver' => $this->getUser(), 'id' => $msg)); 
    $message = new Message(); 
    $message->setSender($this->getUser()); 
    $message->setSentAt(new \Datetime('now')); 
    $message->setReplyof($isforme); 
    $message->setReceiver($isforme->getSender()); 
    $form = $this->createForm(new MessageReplyType($em), $message); 

EDIT

Ok, vì vậy tôi làm một cái gì đó mà làm việc, bằng cách thêm một lĩnh vực ẩn và hardcoding nhiều hình thức thay vì sử dụng FormTypes, nhưng tôi vẫn nghĩ rằng điều này có thể được thực hiện trong một tốt hơn, cách tái sử dụng nhiều hơn.

    <form name="privatemessagebundle_message" method="post" action="" id="{{ reply.id }}"> 
         <div><label for="privatemessagebundle_message_title" class="required">Title</label><input 
            type="text" id="privatemessagebundle_message_title" 
            name="privatemessagebundle_message[title]" required="required" maxlength="50"></div> 
         <div><label for="privatemessagebundle_message_content" class="required">Content</label><textarea 
            id="privatemessagebundle_message_content" 
            name="privatemessagebundle_message[content]" required="required"></textarea></div> 
         <input type="hidden" id="privatemessagebundle_message_replyof" 
           name="privatemessagebundle_message[replyof]" value="{{ reply.id }}"> 
         <input type="submit"> 
         <input type="hidden" id="privatemessagebundle_message__token" 
           name="privatemessagebundle_message[_token]" 
           value="{{ csrf_token('privatemessagebundle_message') }}"> 
        </form> 

Bất kỳ ai có ý tưởng nào tốt hơn?

+0

Dường như văn bản có thể được khởi tạo tốt hơn bằng cách sử dụng Javascript, vì vậy bạn chỉ cần một biểu mẫu duy nhất. Biểu mẫu đó có thể có id 'replyTo' làm trường ẩn. Bằng cách đó bạn chỉ cần một văn bản phải không? – Rvanlaak

+0

Điều đó đòi hỏi nhiều hơn một chút JS như replyTo phải thay đổi giá trị mỗi khi bạn bấm vào một nút trả lời, quá. Nó cũng dễ bị tấn công hơn một chút so với CSRF. Tôi nghĩ rằng giải pháp của tôi, trong khi phức tạp, là một chút thanh lịch hơn, nhưng bạn cũng khá tốt. –

Trả lời

6

Tôi đã làm được! Tôi đã sử dụng câu trả lời từ số question này.

Vì tôi đang sử dụng vòng lặp foreach và chúng có thể hơi yếu về hiệu suất, bất kỳ ai có ý tưởng tốt hơn đều được hoan nghênh. Vẫn còn tiền thưởng để nhận.

Tôi đang tạo biểu mẫu cho từng biểu mẫu của mình thông qua createNamedBuilder. Họ sẽ có các tên khác nhau, do đó các id và Symfony khác nhau sẽ hiển thị tất cả chúng. Sau đó, tôi có thể hiển thị chúng ở nơi tôi muốn và xử lý yêu cầu của họ tốt thông qua id duy nhất của họ được lấy từ cơ sở dữ liệu.

$genforms = $this->genReplyForms($isforme); // run the function for my message 
      $forms_views = $genforms['views']; // pass to the view 
      $forms= $genforms['forms']; // handle request... 

Đây là chức năng tạo biểu mẫu. Nó đệ quy tạo ra chúng cho mỗi câu trả lời của thông điệp của tôi.

public function genReplyForms(Message $message) 
{ 

    $id = $message->getId(); 

    $msgreply[$id] = new Message(); 

    $forms[$id] = $this->container 
     ->get('form.factory') 
     ->createNamedBuilder('form_'.$id, new MessageReplyType(), $msgreply[$id]) 
     ->getForm(); 

    $forms_views[$id] = $forms[$id]->createView(); 


    $result = array(array(), array()); 

    $result['forms'][$id] = $forms[$id]; 
    $result['views'][$id] = $forms_views[$id]; 


    if (sizeof($message->getReplies())) { 

     foreach ($message->getReplies() as $reply) { 

      $child = $this->genReplyForms($reply); 

      $result['forms'] = $result['forms'] + $child['forms']; 
      $result['views'] = $result['views'] + $child['views']; 

     } 

    } 

    return $result; 
} 

MessageReplyType chỉ cần đầu vào của người dùng. Mọi thứ khác được xử lý trong bộ điều khiển

 $builder 
     ->add('title') 
     ->add('content', 'textarea') 
    ; 

Ngoài ra, nhánh đơn giản của tôi. Tôi cũng đã đơn giản hóa cuộc gọi macro. Đã làm một vòng lặp foreach không cần thiết cho thông điệp đầu tiên thay vì chỉ đơn giản là chuyển nó tới macro.

{% macro displayReply(reply, forms) %} 
    {% import _self as macros %} 


    {# <li> id: {{ reply.id }} </li> 
    <li> sent by: {{ reply.sender }} </li> 
    <li> title: {{ reply.title }} </li> 
    <li> content: {{ reply.content }} </li> 
    <li> date: {{ reply.sentAt|date('d-m-Y H:i:s') }} </li> 
    <a href="{{ path('private_message_new',{'msg':reply.id}) }}"> reply </a> 
    <hr> #} 
    <div class="panel panel-default"> 
     <div class="panel-body"> 
      <div class="message-info"> 
       <input type="hidden" name="messageid" id="messageId" value="{{ reply.id }}"> 

       <div class="message-title clearfix"> 
        <h4 class="pull-left">{{ reply.title }}</h4> 
       </div> 
       <hr class="lite-line"> 
       <div class="message-sender clearfix"> 
        <div class="pull-left sender"> 
         {{ reply.sender }} 
        </div> 
        <div class="pull-right"> 
         to <b>{{ (reply.receiver==app.user)?'me':reply.receiver }}</b> on <span 
           class="message-timestamp">{{ reply.sentAt|date('F d, Y H:i:s') }}</span> 
         {# <a class="btn btn-start-order" role="button" 
          href="{{ path('private_message_new',{'msg':reply.id}) }}">Reply</a> #} 
        </div> 

       </div> 
       <hr class="lite-line"> 
       <div class="message-box clearfix"> 
        <span>{{ reply.content | replace({"<script>" : "", "</script>" : ""}) | raw }}</span> 
       </div> 


       {{ form_start(forms[reply.id]) }} 
       <input type="submit"> 
       {{ form_end(forms[reply.id]) }} 



       {# NU STERGE! #} 
       {# 
       <form name="privatemessagebundle_message" method="post" action="" id="{{ reply.id }}"> 
        <div><label for="privatemessagebundle_message_title" class="required">Title</label><input 
           type="text" id="privatemessagebundle_message_title" 
           name="privatemessagebundle_message[title]" required="required" maxlength="50"></div> 
        <div><label for="privatemessagebundle_message_content" class="required">Content</label><textarea 
           id="privatemessagebundle_message_content" 
           name="privatemessagebundle_message[content]" required="required"></textarea></div> 
        <input type="hidden" id="privatemessagebundle_message_replyof" 
          name="privatemessagebundle_message[replyof]" value="{{ reply.id }}"> 
        <input type="submit"> 
        <input type="hidden" id="privatemessagebundle_message__token" 
          name="privatemessagebundle_message[_token]" 
          value="{{ csrf_token('privatemessagebundle_message') }}"></form>#} 
       {# NU STERGE! #} 

      </div> 
     </div> 
    </div> 
    {% for reply in reply.replies %} 

     {% if loop.first %}<div>{% endif %} 
     {{ macros.displayReply(reply,forms) }} 
     {% if loop.last %}</div>{% endif %} 

    {% endfor %} 
{% endmacro %} 

{% import _self as macros %} 
{# use the macro #} 

<div class="message-back"> 
    <a class="btn btn-start-order-dark btn-block" role="button" 
     href="{{ path('private_message',{'page':'inbox'}) }}"> 
     <span class="fa fa-undo"></span> Go back 
    </a> 
</div> 

<div class="replies"> 
    {{ macros.displayReply(message, forms) }} 
</div> 

Một lần nữa, tôi vẫn đang tìm kiếm các giải pháp thay thế hiệu quả hơn, vì vậy hãy đăng chúng.

Các vấn đề liên quan