Symfony2 1:M Post:评论情况。如何将父Post obj传递给子注释视图/表单

时间:2014-03-17 09:48:09

标签: symfony

一个Symfony2新手问题。

说我有1:M帖子:评论情况。

在单个帖子的“显示”视图中,我希望有一个新表单来创建评论,显然是对所显示帖子的评论。

默认情况下做的事情,我得到一个带有select的新表单,其中的选项都是Post(注意:显示的Post确实是选中的选项),这是好的但不太好。

我无法使用隐藏字段定义新表单,其隐藏字段的值以某种方式显示的帖子或其ID。

Symfony2是否需要使用数据转换器即使是这样的基本任务? 欢迎帮助。

2 个答案:

答案 0 :(得分:0)

您可以创建一条评论路线,其父母帖子的ID为url参数,如下所示:

POST: http://localhost/post/123/comment   (creates a comment for post 123)

您的routing.yml可能如下所示:

acme_post_create_comment:
   path: /post/{post_id}/comment
   requirements: { post_id: "\d+" }
   methods: "POST"
   defaults: { _controller: ... }

根据您创建表单的方式,您必须指定此路线和父帖作为表单的操作(有关详细信息,请参阅表单上的Symfony文档)。

您的控制器可能如下所示:

class PostController extends Controller
{
    ...

    public function createCommentAction(Request $request, $post_id)
    {
        $em = $this->getDoctrine()->getManager();
        $post = $em->getrepository('AcmeBlogBundle:Post')->find($post_id);
        if (!$post) {
            throw $this->createNotFoundException('post not found');
        }
        $comment = new Comment();
        $comment->setPost($post);
        $form = $this->createForm(new CommentForm(), $comment);
        $form->handleRequest($request);

        if ($form->isValid()) {
            // Persist comment and redirect to post
        }
        // Display comment form with errors
    }

答案 1 :(得分:0)

以下与Data Transformer的工作方式相比,它非常简单。 它几乎与文档示例http://symfony.com/doc/current/cookbook/form/data_transformers.html

相同
<?php
 /* src/Mario/Bundle/BlogBundleForm/DataTransformer/PostToIdTransformer.php */
namespace Mario\Bundle\BlogBundle\Form;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Mario\Bundle\BlogBundle\Entity\Issue;

class PostToIdTransformer implements DataTransformerInterface
{
/**
 * @var ObjectManager
 */
private $om;

/**
 * @param ObjectManager $om
 */
public function __construct(ObjectManager $om)
{
    $this->om = $om;
}

/**
 * Transforms an object (post) to a string (id).
 *
 * @param  Post|null $post
 * @return string
 */
public function transform($post)
{
    if (null === $post) {
        return "";
    }

    return $post->getId();
}

/**
 * Transforms a string (id) to an object (post).
 *
 * @param  string $id
 *
 * @return Post|null
 *
 * @throws TransformationFailedException if object (post) is not found.
 */
public function reverseTransform($id)
{
    if (!$id) {
        return null;
    }

    $post = $this->om
        ->getRepository('MarioBlogBundle:Post')
        ->findOneBy(array('id' => $id))
    ;

    if (null === $post) {
        throw new TransformationFailedException(sprintf(
            'An post with id "%s" does not exist!',
            $id
        ));
    }

    return $post;
}
}
?>

然后在我的CommentType中,我定义

public function buildForm(FormBuilderInterface $builder, array $options)
{

    $entityManager = $options['em'];
    $transformer = new PostToIdTransformer($entityManager);
    $builder
        ->add('author')
        ->add('email')
        ->add('comment')
        ->add(
        $builder->create('post', 'hidden')
            ->addModelTransformer($transformer));
}

我还需要在createForm

的CommentController定义中传递$ em
/**
* Creates a form to create a Comment entity.
*
* @param Comment $entity The entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createCreateForm(Comment $entity)
{
    $form = $this->createForm(new CommentType(), $entity, array(
        'action' => $this->generateUrl('Mario_Comment_create'),
        'method' => 'POST',
        'em' => $this->getDoctrine()->getEntityManager()
    ));
    $form->add('submit', 'submit', array('label' => 'Scrivi commento'));
    return $form;
}

所以,很容易。谢谢干杯

(评论:我想说,对于M:1关系,默认情况下,Symfony2应该为子obj创建一个新形式,其中(隐藏)值仅用于(唯一的)父obj.Symfony2确实知道该值。)