0

I successfuly created working bundle for my blog, including administration of articles, but I'm stuck with Comments. I want to separate comments by user and anonymous user. If user is logged, then he will not see field for Author and he will not see captcha. I think, that this problem I can solve with one if in the form builder (if user is fully authenticated) and then in my TWIG template too. But, it is the good solution? Isn't there any easier way? So my Comment.php will have this form:

<?php

namespace Acme\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity
 * @ORM\Table(name="comments") 
 */
class Comment
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;              

    /**
     * @ORM\Column(type="string", length=200)    
     * @Assert\NotBlank(
     *      message = "Name cannot be blank"      
     * )    
     * @Assert\Length(
     *      min = "3",
     *      minMessage = "Name is too short"         
     * )     
     */     
    private $author;

    /**
     * @ORM\ManyToOne(targetEntity="\Acme\UserBundle\Entity\User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")       
     */
    private $user_id;

    /**
     * @ORM\Column(type="string", length=200)
     * @Assert\NotBlank(
     *      message = "E-mail cannot be blank"      
     * )    
     * @Assert\Length(
     *      min = "3",
     *      minMessage = "E-mail is too short"         
     * )
     */
    private $email;              

    /**
     * @ORM\Column(type="text")
     * @Assert\NotBlank(
     *      message = "Message cannot be blank"
     * )     
     * @Assert\Length(
     *      min = "3",
     *      minMessage = "Message is too short"         
     * )     
     */
    private $content;

    /**
     * @ORM\ManyToOne(targetEntity="Article", inversedBy="comments")
     * @ORM\JoinColumn(referencedColumnName="id")
     */
    private $article;              

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set author
     *
     * @param string $author
     * @return Comment
     */
    public function setAuthor($author)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return string 
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Set email
     *
     * @param string $email
     * @return Comment
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string 
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set content
     *
     * @param string $content
     * @return Comment
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string 
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set article
     *
     * @param \Acme\BlogBundle\Entity\Article $article
     * @return Comment
     */
    public function setArticle(\Acme\BlogBundle\Entity\Article $article = null)
    {
        $this->article = $article;

        return $this;
    }

    /**
     * Get article
     *
     * @return \Acme\BlogBundle\Entity\Article 
     */
    public function getArticle()
    {
        return $this->article;
    }

    /**
     * Set user_id
     *
     * @param \Acme\UserBundle\Entity\User $userId
     * @return Comment
     */
    public function setUserId(\Acme\UserBundle\Entity\User $userId = null)
    {
        $this->user_id = $userId;

        return $this;
    }

    /**
     * Get user_id
     *
     * @return \Acme\UserBundle\Entity\User 
     */
    public function getUserId()
    {
        return $this->user_id;
    }

This was my first problem, then my second problem I see with displaying comments (rather author name). I'm not sure, how to create a new value into my $comments property in my Controller (if property user_id is not NULL, then load from User object information about this user with this ID, and if it is NULL, then use author property. And if is comment by User, the author name will be underlined. Also, it is work for my Controller or I can do it in my TWIG template?

My questions in short:

  • Which is the best method displaying "Write your comment" form build with logged and not-logged users (most effetive, not sure using if in my form builder and in my TWIG template)
  • How to separate comments by anonymous/registered users and if is comment by registered user, his name will be underlined
4

2 回答 2

0

I hope that You use FormBuilder for creating Your form.

Add to Your CommentType contructor new argument like $user

private $user;

public function __construct($user) {
    $this->user = $user;
}

public function buildForm(FormBuilderInterface $builder, array $options) {
    if(!is_null($this->user)) {
        $builder->add(); ...
    }
}

in Your controller:

$user = null;
$securityContext = $this->container->get('security.context');
if( $securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED') ){
    // authenticated REMEMBERED, FULLY will imply REMEMBERED (NON anonymous)
    $user = $this->user();
}

$form = $this->createForm(new CommentType($user), $comment);

Second question:

You should only check if user_id is not null, when not null -> undeline, is null -> not undeline.

于 2013-10-17T15:09:19.490 回答
0

So I used the answer by @Dawid Sajdak and tried to put it into my code. So for first, I've edited my Comment.php entity, where I added validation groups:

<?php

namespace Acme\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * @ORM\Entity(repositoryClass="Acme\BlogBundle\Entity\CommentRepository")
 * @ORM\Table(name="comments") 
 */
class Comment
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;              

    /**
     * @ORM\Column(type="string", length=200, nullable=true)    
     * @Assert\NotBlank(
     *      message = "Name cannot be blank",
     *      groups = {"not_logged"}           
     * )    
     * @Assert\Length(
     *      min = "3",
     *      minMessage = "Name is too short",
     *      groups = {"not_logged"}              
     * )     
     */     
    private $author;

    /**
     * @ORM\ManyToOne(targetEntity="\Acme\UserBundle\Entity\User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")       
     */
    private $user_id;

    /**
     * @ORM\Column(type="string", length=200, nullable=true)
     * @Assert\NotBlank(
     *      message = "E-mail cannot be blank",
     *      groups = {"not_logged"}           
     * )    
     * @Assert\Email(
     *      message = "E-mail is not valid",
     *      groups = {"not_logged"}     
     * )     
     */
    private $email;

    /**
     * @ORM\Column(type="datetime")   
     */
    protected $published;              

    /**
     * @ORM\Column(type="text")
     * @Assert\NotBlank(
     *      message = "Message cannot be blank"
     * )     
     * @Assert\Length(
     *      min = "3",
     *      minMessage = "Message is too short"         
     * )     
     */
    private $content;

    /**
     * @ORM\ManyToOne(targetEntity="Article", inversedBy="comments")
     * @ORM\JoinColumn(referencedColumnName="id")
     */
    private $article;              

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set author
     *
     * @param string $author
     * @return Comment
     */
    public function setAuthor($author)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return string 
     */
    public function getAuthor()
    {
        return $this->author;
    }

    /**
     * Set email
     *
     * @param string $email
     * @return Comment
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string 
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set content
     *
     * @param string $content
     * @return Comment
     */
    public function setContent($content)
    {
        $this->content = $content;

        return $this;
    }

    /**
     * Get content
     *
     * @return string 
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * Set article
     *
     * @param \Acme\BlogBundle\Entity\Article $article
     * @return Comment
     */
    public function setArticle(\Acme\BlogBundle\Entity\Article $article = null)
    {
        $this->article = $article;

        return $this;
    }

    /**
     * Get article
     *
     * @return \Acme\BlogBundle\Entity\Article 
     */
    public function getArticle()
    {
        return $this->article;
    }

    /**
     * Set user_id
     *
     * @param \Acme\UserBundle\Entity\User $userId
     * @return Comment
     */
    public function setUserId(\Acme\UserBundle\Entity\User $userId = null)
    {
        $this->user_id = $userId;

        return $this;
    }

    /**
     * Get user_id
     *
     * @return \Acme\UserBundle\Entity\User 
     */
    public function getUserId()
    {
        return $this->user_id;
    }

    /**
     * Set published
     *
     * @param \DateTime $published
     * @return Comment
     */
    public function setPublished($published)
    {
        $this->published = $published;

        return $this;
    }

    /**
     * Get published
     *
     * @return \DateTime 
     */
    public function getPublished()
    {
        return $this->published;
    }
}

I've used validation groups because without them, if you are an administrator, you will not see Name and E-mail field and after submitting form, you will get error messages: "Name cannot be blank" ...

So next step was creating a new CommentType.php:

<?php

namespace Acme\BlogBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class CommentType extends AbstractType
{
    private $user;

    public function __construct($user) {
        $this->user = $user;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\BlogBundle\Entity\Comment',
            'csrf_protection' => true,
        ));
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        if(is_null($this->user)) {
            $builder->add('author', 'text', array('label' => 'Author', 'validation_groups' => array('not_logged')))
                    ->add('email', 'text', array('label' => 'E-mail (will not show)', 'validation_groups' => array('not_logged')));
        }        
            $builder->add('content', 'textarea', array('label' => 'Text',))
                    ->add('save', 'submit', array('label' => 'Submit'));
    }

    public function getName()
    {
        return 'comment';
    }
}

Then there is a DefaultController.php, where I added a few logical questions, if user is logged or not:

public function showAction($slug, Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $article = $em->getRepository('AcmeBlogBundle:Article')->findOneBySlug($slug);

    if(!$article)
    {
        throw $this->createNotFoundException('This article does not exists');
    }

    $user = null;
    if(true === $this->get('security.context')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
        $user = $this->getUser();  // get $user object
    }

    $comment = new Comment();
    $comment->setArticle($article);

    $form = $this->createForm(new CommentType($user), $comment);
    $form->handleRequest($request);

    if($form->isValid())
    {
        $comment->setPublished(new \DateTime('now')); // don't forget to set publish date

        if($user) {
            $comment->setUserId($user); // set User_id
        }

        $em = $this->getDoctrine()->getManager();
        $em->persist($comment);
        try {
            $em->flush();
        } catch (\PDOException $e) {
            // sth
        }
        $this->get('session')->getFlashBag()->add(
            'success',
            'Your comment was succesfully added'
        );
        return $this->redirect($this->generateUrl('default_blog_show', array('slug' => $slug)).'#comments'); // redirect  
    }

    return $this->render('AcmeBlogBundle:Default:show.html.twig', array('article' => $article, 'form' => $form->createView()));
}

And now, we need to prepare our show.html.twig to display our comments and form for a new comment:

{% for comment in article.comments %}
  <div style="border: 1px solid black; margin: 10px 0; padding: 5px;">
      <div style="border-bottom: 1px solid black;">
          {% if app.user %}{% if comment.userId is null %}{{ comment.email }}{% else %}{{ comment.userId.email }}{% endif %}{% endif %}<p>Written by: {% if comment.userId is null %}{{ comment.author }}{% else %}<strong>{{ comment.userId.username }}</strong>{% endif %} at {{ comment.published|date('d.n.Y H:i:s') }}</p>
      </div>
      <p>{{ comment.content }}</p>
  </div>
{% else %}
<h2>No comments, be first!</h2>
{% endfor %}
<hr />
<fieldset style="padding: 10px; margin: 10px; border: 1px solid black;">
    <legend style="background-color: skyblue; padding: 5px;">New comment</legend>
{{ form(form) }}
</fieldset>

And it's done. At the end, if you want to sort comments by publish date ASC, you have to add annotation on $comments property into Article.php entity:

/**
 * @ORM\OneToMany(targetEntity="Comment", mappedBy="article")
 * @ORM\OrderBy({"published" = "ASC"})     
 */
private $comments;  
于 2013-10-31T14:23:41.257 回答