2015-09-17 21 views
9

私は自分のユーザーがメッセージを送信できるプライベートメッセージバンドル/エンティティを持っています。受信したメッセージごとに返信フォームのテキストフィールドを追加

/** 
* @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(); 
} 

お知らせreplyofフィールドを、それは別のmessageへの参照、およびmessagesの配列へreplies 1参照:

そのフィールドは以下の通りです。 replyofがヌルの場合、メッセージはどのメッセージの返信でもありません。

私は、ユーザーのメッセージとそのメッセージのすべての返信を表示するマクロを持つ小枝テンプレートを持っています。私がしたいのは、それぞれのメッセージに返信を加えることができる、Gmailのような返信用のテキストフィールドがあることです。

しかし、テンプレートに追加すると、1つのIDがあるため1つだけがレンダリングされます。返信後に返信フォームを追加するにはどうすればよいですか? FormTypeはどのように見えるのですか?ここで

も私の小枝テンプレートです:私は最初のツリーとしてすべての返信を表示することにマクロを適用し、その後、メッセージを表示する

{% 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 %} 

注意してください。返信の返信も、リーフノードまで、再帰的に表示されます。私はそれぞれの後に 'replyform'を追加しますが、私はFormTypeがどうあるべきかわかりません。

私の返信フォームタイプはこのようなものですが、間違っていると確信しています。

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

} 

返信の他のフィールドについては、私はコントローラでそれらを管理しています。私はフォームからメッセージを受け取った後にこれを行うべきだと思う。これと同じように、formdataからtitle、content、およびreplyofを取得します。

$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); 

[OK]をEDIT

、ので、私は隠しフィールドを追加し、代わりにFormTypesを使用しての複数のフォームをハードコーディングすることで、作品に何かを作ったが、私はまだ、これはより良いで行うことができると思いますより再利用可能な方法。

    <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> 

誰でも良いアイデアがありますか?

+0

テキストエリアのように見えますが、Javascriptを使用して初期化する方がよいので、1つのフォームしか必要ありません。そのフォームは 'replyTo' idを隠しフィールドとして持つことができます。そうすれば、1つのテキストエリアだけが必要ですか? – Rvanlaak

+0

これはreplyToが返信ボタンをクリックするたびに値を変更する必要があるため、もう少しJSを必要とします。それはCSRFに対してももう少し脆弱です。私のソリューションは複雑だが、もう少しエレガントだと思うが、あなたもかなり良い。 –

答えて

6

私はそれをしました!私はこのquestionの答えを使用しました。

私はforeachループを使用しているので、パフォーマンスが少し低いかもしれないので、より良いアイデアを持つ人は歓迎されます。それでも受け取る恩恵があります。

私は自分のフォームごとにcreateNamedBuilderを通してフォームを作成しています。彼らは異なる名前を持ち、異なるIDとSymfonyがそれらをすべてレンダリングします。次に、データベースから取得した一意のIDを使用して、必要な場所にレンダリングし、要求を正しく処理できます。

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

これはフォームを生成した関数です。私のメッセージの返信ごとにそれらを再帰的に生成します。

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にはユーザー入力が必要です。他のすべてはコントローラで処理されます

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

また、私の単純化された小枝です。私もマクロ呼び出しを簡略化しました。単にマクロに渡すのではなく、最初のメッセージに対して不要なforeachループを実行していました。

{% 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> 

私はまだ、より効率的な代替案を探していますので、投稿してください。

関連する問題