为每封收到的邮件添加回复表单文本字段

时间:2015-09-17 13:49:04

标签: php symfony twig symfony-forms

我有一个私人消息包/实体,允许我的用户在它们之间发送消息。

其字段如下:

/**
 * @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字段,它引用另一个messagereplies引用messages数组。如果replyof为空,则该消息不是任何消息的回复。

我有一个带有宏的树枝模板,显示用户的消息以及该消息的所有回复。我想要做的是在每个下面都有一个回复文本字段,就像Gmail一样,允许我为每条消息添加回复。

但是当我将它添加到模板时,只渲染了一个,因为它只有一个Id。如何在每次回复后添加回复表格?他们的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 %}

请注意,我首先显示消息,然后将宏应用于它,将所有回复显示为树。它将以递归方式显示回复的回复,一直到叶节点。我添加了一个回复表格&#39;在每个之后,但我不确定FormType应该如何。

我的回复表格类型是这样的,但我确定这是错误的。

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

}

至于回复的其他字段,我在控制器中处理它们。我认为我应该在收到表单中的消息之后这样做。这样的东西,从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);

修改

好的,所以我做了一些有用的东西,通过添加一个隐藏字段并硬编码多个表单而不是使用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>

有人有更好的想法吗?

1 个答案:

答案 0 :(得分: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>

同样,我仍然在寻找更好或更有效的替代方案,所以请发布它们。