我有三个实体:用户,评论,文章。用户可以发表评论/文章。
在我的文章控制器中,我有一个名为commentAction的方法,它应该返回注释表单。我在文章显示模板中调用此控制器。它有效,但当我尝试验证表单时会出现问题。
我想将用户返回到文章显示页面,并显示评论表单错误。
两个问题:表单将我们带到commentAction而不是回到showAction。另外,由于某种原因,我无法获得验证错误。
我已经合并了一个货运代理(无论如何它似乎都不正常)。有人能告诉我正确的方法吗?
非常感谢!
P.S。我是Symfon的新手所以如果你能提醒我,如果我违反了任何最佳做法我会很感激你,如果你让我知道:)。
评论实体:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Comment
*
* @ORM\Table(name="comment")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CommentRepository")
*/
class Comment
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var int $rating
*
* @ORM\Column(name="rating", type="smallint")
* @Assert\NotBlank()
*/
private $rating;
/**
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
*/
private $title;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="comments")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="Article", inversedBy="comments")
* @ORM\JoinColumn(name="article_id", referencedColumnName="id")
*/
private $article;
/**
* @var string
*
* @ORM\Column(name="comment", type="text", nullable=true)
*/
private $comment;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set rating
*
* @param integer $rating
*
* @return Comment
*/
public function setRating($rating)
{
$this->rating = $rating;
return $this;
}
/**
* Get rating
*
* @return int
*/
public function getRating()
{
return $this->rating;
}
/**
* Set title
*
* @param string $title
*
* @return Comment
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set userId
*
* @param integer $userId
*
* @return Comment
*/
public function setUserId($userId)
{
$this->userId = $userId;
return $this;
}
/**
* Get userId
*
* @return int
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set comment
*
* @param string $comment
*
* @return Comment
*/
public function setComment($comment)
{
$this->comment = $comment;
return $this;
}
/**
* Get comment
*
* @return string
*/
public function getComment()
{
return $this->comment;
}
/**
* Set user
*
* @param \AppBundle\Entity\User $user
*
* @return Comment
*/
public function setUser(\AppBundle\Entity\User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return \AppBundle\Entity\User
*/
public function getUser()
{
return $this->user;
}
/**
* Set article
*
* @param \AppBundle\Entity\Article $article
*
* @return Comment
*/
public function setArticle(\AppBundle\Entity\Article $article = null)
{
$this->article = $article;
return $this;
}
/**
* Get article
*
* @return \AppBundle\Entity\User
*/
public function getArticle()
{
return $this->article;
}
}
文章控制器
<?php
namespace AppBundle\Controller;
use AppBundle\Entity\Article;
use AppBundle\Entity\Comment;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\General\HelperClass;
use AppBundle\Form\CommentType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
/**
* Article controller.
*
* @Route("article")
*/
class ArticleController extends Controller
{
/**
* Show all article entities.
*
* @Route("/", name="article_index")
* @Method("GET")
*/
public function indexAction(Request $request)
{
return $this->render('article/index.html.twig');
}
/**
* Lists all article entities, optionally sorted.
*
* @Route("/list", name="article_list")
* @Method("GET")
*/
public function listAction(Request $request)
{
//if we're passing a sort_by it'll be an embed in twig template.
$sortBy = $request->get('sort_by');
$em = $this->getDoctrine()->getManager();
if('average-rating' === $sortBy){
$sortBy = "avg_rating";
$articles = $em->getRepository('AppBundle:Article')->getArticlesByAverageRating($sortBy);
} else {
$sortBy = "name";
$articles = $em->getRepository('AppBundle:Article')->getArticlesByAverageRating($sortBy);
}
return $this->render('article/list.html.twig', array(
'articles' => $articles,
));
}
protected function getComment(\AppBundle\Entity\User $user, \AppBundle\Entity\Article $article, \AppBundle\Entity\Comment $comment){
$em = $this->getDoctrine()->getManager();
$userId = $user->getId();
$existingComment = $em->getRepository('AppBundle:Comment')->getCommentByUserIdAndArticleId($user, $article);
if($existingComment) {
$existingComment->setRating($comment->getRating());
$existingComment->setTitle($comment->getTitle());
$existingComment->setComment($comment->getComment());
$comment = $existingComment;
}
return $comment;
}
/**
* Creates a new article entity.
*
* @Route("/new", name="article_new")
* @Method({"GET", "POST"})
*/
public function newAction(Request $request)
{
$article = new Article();
$form = $this->createForm('AppBundle\Form\ArticleType', $article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
//Set the user
$article = $form->getData();
$article->setUser($user);
//Set Created Date
$date = new \DateTime("now");
$article->setCreatedDate($date);
$em->persist($article);
$em->flush($article);
return $this->redirectToRoute('article_show', array('id' => $article->getId()));
}
return $this->render('article/new.html.twig', array(
'article' => $article,
'form' => $form->createView(),
));
}
/**
* Finds and displays a article entity.
*
* @Route("/{id}", name="article_show")
* @Method("GET")
*/
public function showAction(Article $article)
{
$deleteForm = $this->createDeleteForm($article);
return $this->render('article/show.html.twig', array(
'article' => $article,
'delete_form' => $deleteForm->createView(),
));
}
/**
* The comment form for articles
*
* @Route("/{id}/comment", name="article_comment")
* @Method({"GET", "POST"})
*/
public function commentAction(Request $request, Article $article)
{
$comment = new Comment();
//Build the comment form.
$commentForm = $this->createFormBuilder($comment)
->add('comment', CommentType::class, array("label" => FALSE))
->setAction($this->generateUrl('article_comment', array('id' =>$article->getId())))
->getForm();
$commentForm->handleRequest($request);
//THIS IS MY FORWARDER BUT I SEEM TO LOSE ALL FORM DATA WHEN I DO THIS SO I DON"T THINK IT"S RIGHT!!
if ($commentForm->isSubmitted() && !$commentForm->isValid()) {
return $this->forward(
'AppBundle:Article:show',
array(
'form' => $commentForm->createView(),
'article' => $article,
)
);
}
if ($commentForm->isSubmitted() && $commentForm->isValid()) {
//Update existing user or create new
$em = $this->getDoctrine()->getManager();
$comment = $commentForm->getData()->getComment();
$user = $this->getUser();
$comment = $this->getComment($user, $article, $comment);
//Set the user and article for the comment.
$comment->setUser($user);
$comment->setArticle($article);
$em->persist($comment);
$em->flush($comment);
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('article_show', array('id' => $article->getId()));
}
return $this->render('article/comment.html.twig', array(
'form' => $commentForm->createView(),
));
}
/**
* Displays a form to edit an existing article entity.
*
* @Route("/{id}/edit", name="article_edit")
* @Method({"GET", "POST"})
*/
public function editAction(Request $request, Article $article)
{
$deleteForm = $this->createDeleteForm($article);
$editForm = $this->createForm('AppBundle\Form\ArticleType', $article);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('article_edit', array('id' => $article->getId()));
}
return $this->render('article/edit.html.twig', array(
'article' => $article,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
/**
* Deletes a article entity.
*
* @Route("/{id}", name="article_delete")
* @Method("DELETE")
*/
public function deleteAction(Request $request, Article $article)
{
$form = $this->createDeleteForm($article);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->remove($article);
$em->flush($article);
}
return $this->redirectToRoute('article_index');
}
/**
* Creates a form to delete a article entity.
*
* @param Article $article The article entity
*
* @return \Symfony\Component\Form\Form The form
*/
private function createDeleteForm(Article $article)
{
return $this->createFormBuilder()
->setAction($this->generateUrl('article_delete', array('id' => $article->getId())))
->setMethod('DELETE')
->getForm()
;
}
}
显示文章树枝
{% extends 'base.html.twig' %}
{% block body_id 'articlepage' %}
{% block body %}
<h1>Article: {{ article.name }}</h1>
<div class="well"><div class="media">
<div class="media-left media-top">
<img class="media-object" src="{{ article.thumbnail }}">
</div>
<div class="media-body">
<h4 class="media-heading">{{ article.name }}</h4>
<p>{{ article.description }}</p>
</div>
</div></div>
{{ render(controller('AppBundle:Comment:index', {'article_id': article.id})) }}
{% if is_granted('ROLE_USER') -%}
<h2>Submit a new comment:</h2>
{{ render(controller('AppBundle:Article:comment', {'id': article.id})) }}
{% else %}
<h3>Log In To Leave A Comment!</h3>
<p>Click <a href="{{ path('fos_user_security_login') }}">here</a> to log in or <a href="{{ path('fos_user_registration_register') }}">here</a> to register</p>
{% endif %}
{% endblock %}
评论文章Twig
{% extends 'base.html.twig' %}
{% form_theme form 'form/fields.html.twig' %}
{% block body %}
{{ form_start(form) }}{{ form_errors(form.comment.comment) }}{{form_errors(form.comment.title) }}
<div class="form-group">{{ form_row(form.comment.title) }}</div>
<div class="form-group">{{ form_row(form.comment.rating) }}</div>
<div class="form-group">{{ form_row(form.comment.comment) }}</div>
<input class="btn btn-default" type="submit" value="Create" />
{{ form_end(form) }}
{% endblock %}
答案 0 :(得分:0)
将您的show动作放在createFormBuilder中的 - &gt; setAction()中,而不是像您当前拥有的那样进行评论操作。
->setAction($this->generateUrl('article_show', array('id' =>$article->getId())))
您需要在show动作中处理解析表单。我总是建议使用错误冒泡来显示页面顶部的所有错误。在您的createFormBuilder中,只需修改您的添加:
>add('comment', CommentType::class, array("label" => false, 'error_bubbling' => true))
然后在您的Twig中,将其放在您的表单上方:
{% if form_errors(form)|length > 10 %}
<div class="col-md-10 col-md-offset-1">
<div class="alert alert-danger fade-in">
{{ form_errors(form) }}
</div>
</div>
{% endif %}
答案 1 :(得分:0)
我假设您可以在文章中添加许多评论。然后,您在这些实体之间拥有一对多关系。这必须在使用注释的实体声明中定义。有关详细信息,请参阅此文章:http://symfony.com/doc/current/doctrine/associations.html
使用此定义,您可以为实体Comment创建单独的表单类型。在实体文章的表单类型中,您将字段“comment”定义为 CollectionType 。 Symfony使用实体Comment的表单类型在实体Article中呈现字段注释。有关详细信息,请参阅此文章:https://symfony.com/doc/current/form/form_collections.html