从另一个动作保存表单

时间:2014-12-17 15:47:32

标签: php symfony

我有两个动作,GetAllPost和newComment 我有一个包含很多帖子的页面,每个帖子都有commentForm

PostController中

public function getPostAction () {
     return array(
    );
}

枝条

{% for post in app.user.posts %}
        <p>{{ post.id }} - {{ post.description }} </p>
        {{ render(controller("ADVCommentBundle:Comment:newComment" ,{ 'id': post.id,'redirect':'get_post' } )) }}
        <hr>
    {%endfor%}

CommentController

public function newCommentAction (Request $request, Post $post) {
        $em = $this->getEm();
        $comment = new Comment();
        $form = $this->createForm(new CommentType(), $comment);
        $form->handleRequest($request);
            if ($form->isValid()) {
                try {
                    $em->beginTransaction();
                    $comment->setPost($post);
                    $em->persist($comment);
                    $em->flush();
                    $em->commit();
                } catch (\Exception $e) {
                    $em->rollback();
                    throw $e;
                }
            } 
        return array(
            'post' => $post,
            'form' => $form->createView(),
        );
    }

TwifFormController

{{ form(form, {'action': path('new_comment',{'id': post.id})})}}

当我插入新评论时,即使我的值无效,我也会重定向到new_comment。 如何重定向到GeTAllPost并显示正确的错误或新的评论?

我尝试使用

return $this->redirect($this->generateUrl('get_post',array('error',$form->getErrors())));

'error_bubbling' => true,,但每次请求一个get_post(GetAllPost)我都会对我的表单进行新的渲染,但我没有看到错误

例如,我想在几个场景中使用newCommentAction。 例如,每个帖子都有我的GetAllPost,但即使在GetSpecificPost,我有一个特定的帖子,我可以插入一个新的评论,但保存(和动作)是相同的。

我是否创建了服务?

更新

在Bonswouar的回答之后。这是我的代码 PostController中

/**
     * @Route("/",name="get_posts")
     * @Template()
     */
    public function getPostsAction () {
        $comment = new Comment();
        return array(
            'commentForms' => $this->createCreateForm($comment),
        );
    }

    private function createCreateForm (Comment $entity) {
        $em = $this->getEm();
        $posts = $em->getRepository('ADVPostBundle:Post')->findAll();
        $commentForms = array();
        foreach ($posts as $post) {
            $form = $this->createForm(new CommentType($post->getId()), $entity);
            $commentForms[$post->getId()] = $form->createView();
        }
        return $commentForms;
    }


    /**
     * @Method({"POST"})
     * @Route("/new_comment/{id}",name="new_comment")
     * @Template("@ADVPost/Post/getPosts.html.twig")
     * @ParamConverter("post", class="ADVPostBundle:Post")
     */
    public function newCommentAction (Request $request, Post $post) {
        $em = $this->getEm();
        $comment = new Comment();

        //Sometimes I Have only One Form
        $commentForms = $this->createCreateForm($comment);

        $form = $this->createForm(new CommentType($post->getId()), $comment);
        $form->handleRequest($request);
        if ($form->isValid()) {
            try {
                $em->beginTransaction();
                $comment->setPost($post);
                $em->persist($comment);
                $em->flush();
                $em->commit();
            } catch (\Exception $e) {
                $em->rollback();
                throw $e;
            }
        } else {
            $commentForms[$post->getId()] = $form->createView();
        }

        return array(
            'commentForms' => $commentForms,
        );
    }

而且我没有任何渲染。 但是,我想在单一帖子中重复使用newCommentAction,我想创建一个表单。我不想使用$commentForms = $this->createCreateForm($comment);,因为我只想要一个表单,我甚至需要更改模板。我该怎么办?

2 个答案:

答案 0 :(得分:3)

如果我没有误会,那么您的问题就是您要在new_comment上发帖,这是一个&#34;子行动&#34;。

你实际上并不需要这个Twig render。 您可以在主Action中生成所需的所有表单,如下所示:

foreach ($posts as $post) {
  $form = $this->createForm(new CommentType($post->getId()), new Comment());
  $form->handleRequest($request);
  if ($form->isValid()) {
    //...
    // Edited : to "empty" the form if submitted & valid. Another option would be to redirect()
    $form = $this->createForm(new CommentType($post->getId()), new Comment());
  }
  $commentForms[$post->getId()] = $form->createView();
}
return array(
  'posts' => $posts,
  'commentForms' => $commentForms,
);

不要忘记在Form类中设置动态名称:

class CommentType extends AbstractType
{
     public function __construct($id) {
         $this->postId = $id;
     }
     public function getName() {
         return 'your_form_name'.$this->postId;
     }
     //...
}

然后通常只需在Twig循环中渲染表单。你应该得到错误。

{% for post in app.user.posts %}
    <p>{{ post.id }} - {{ post.description }} </p>
    {{ form(commentForms[post.id]) }}
    <hr>
{%endfor%}

如果我没有错过应该做的任何事情。

更新:

看到你的更新后,这可能是你想要的控制器(对不起,如果我没有正确理解或者我是否犯了一些错误)

/**
 * @Route("/",name="get_posts")
 * @Template()
 */
public function getPostsAction () {
    $em = $this->getEm();
    $posts = $em->getRepository('ADVPostBundle:Post')->findAll();
    $commentForms = array();
    foreach ($posts as $post) {
        $commentForms[$post->getId()] = $this->createCommentForm($post);
    }
    return array(
        'commentForms' => $commentForms
    );
}

private function createCommentForm (Post $post, $request = null) {
    $em = $this->getEm();
    $form = $this->createForm(new CommentType($post->getId()), new Comment());
    if ($request) {
        $form->handleRequest($request);
        if ($form->isValid()) {
            try {
                $em->beginTransaction();
                $comment->setPost($post);
                $em->persist($comment);
                $em->flush();
                $em->commit();
            } catch (\Exception $e) {
                $em->rollback();
                throw $e;
            }
            $form = $this->createForm(new CommentType($post->getId()), new Comment());
        }
    }
    return $form;
}


/**
 * @Method({"POST"})
 * @Route("/new_comment/{id}",name="new_comment")
 * @Template("@ADVPost/Post/getPosts.html.twig")
 * @ParamConverter("post", class="ADVPostBundle:Post")
 */
public function newCommentAction (Request $request, Post $post) {
    return array(
        'commentForm' => $this->createCommentForm($post, $request);
    );
}

答案 1 :(得分:0)

使用Flash消息设置错误消息怎么样? http://symfony.com/doc/current/components/http_foundation/sessions.html#flash-messages

编辑:根据您的评论进行修改。在您的控制器中,您可以这样做:

foreach ($form->getErrors() as $error) {
    $this->addFlash('error', $post->getId().'|'.$error->getMessage());
}

$this->addFlash('error',  $post->getId().'|'.(string) $form->getErrors(true, false));

这将允许您将错误绑定到您想要的特定帖子,因为您传递了一个字符串,如 355 |此值已被使用。如果您需要知道该字段,可以在Flash消息中为 $ error-&gt; getPropertyPath()添加另一个分隔符,或者您可以覆盖实体本身中的错误名称。

然后在您的控制器中,您可以解析Flash消息,并将它们添加到您的twig模板将检查的数组中:

$errors = array();

foreach ($this->get('session')->getFlashBag()->get('error', array()) as $error)
{
    list($postId, $message) = explode('|', $error);

    $errors[$postId][] = $message;
}

return array('errors' => $errors, ...anything else you send to the template)

现在,您的twig模板可以检查该特定表单上是否存在错误:

{% for post in app.user.posts %}
    {% if errors[post.id] is defined %}
        <ul class="errors">
        {% for error_message in errors[post.id] %}
            <li>{{ error_message }}</li>
        {% endfor %}
        </ul>
    {% endif %}
    <p>{{ post.id }} - {{ post.description }} </p>
    {{ render(controller("ADVCommentBundle:Comment:newComment" ,{ 'id': post.id,'redirect':'get_post' } )) }}
    <hr>
{%endfor%}