Symfony删除文章和评论

问题描述 投票:1回答:1

我正在开发一个包含文章和评论系统的博客,我希望当后端的人删除文章时,文章的评论也会被删除,因为表评论与表文章和表用户有关。

我只想删除文章及其评论。

我试过这段代码,但它不起作用,它给我一个这样的错误:

EntityManager #remove()要求参数1为实体对象,给定NULL。

我尝试用getter和setter获取注释,但它不起作用并且告诉我这个方法在控制器中不存在。

我的控制器:

// remove an article
/**
 * @Route("admin/supprimer/{id}")
 * @param int $id
 * @return Response
 */
public function delete(int $id): Response
{
    $comment = $this->getDoctrine()->getRepository(Comments::class)->find($id);
         
    if ($comment === null) {
        $comments = $this->getDoctrine()->getManager();
        $comments->remove($comment);
        $comments->flush();
    }
 
    $article = $this->getDoctrine()
        ->getRepository(Articles::class)
        ->find($id);

    $manager = $this->getDoctrine()->getManager();
 
    $manager->remove($article);
    $manager->flush();
    $this->addFlash('deleteArticle', 'L\'article a bien étais supprimer');

    return $this->redirectToRoute('app_backoffice_admin');
}

评论实体:

namespace App\Entity;
 
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
 
/**
 * @ORM\Entity(repositoryClass="App\Repository\CommentsRepository")
 */
class Comments
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
 
    /**
     * @ORM\Column(type="text", nullable=false)
     */
    private $commentsContent;
 
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="comments")
     * @ORM\JoinColumn(nullable=false)
     */
    private $userComments;
 
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Articles", inversedBy="comments")
     */
    private $articleComments;
 
    public function __construct()
    {
        $this->userComments = new ArrayCollection();
        $this->articleComments = new ArrayCollection();
    }
 
    public function getId()
    {
        return $this->id;
    }
 
    public function getCommentsContent(): ?string
    {
        return $this->commentsContent;
    }
 
    public function setCommentsContent(?string $commentsContent): self
    {
        $this->commentsContent = $commentsContent;
 
        return $this;
    }
 
    public function getUserComments(): ?User
    {
        return $this->userComments;
    }
 
    public function setUserComments(?User $userComments): self
    {
        $this->userComments = $userComments;
 
        return $this;
    }
 
    public function getArticleComments(): ?Articles
    {
        return $this->articleComments;
    }
 
    public function setArticleComments(?Articles $articleComments): self
    {
        $this->articleComments = $articleComments;
 
        return $this;
    }
}

文章实体:

namespace App\Entity;
 
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\Validator\Constraints as Assert;
use Gedmo\Mapping\Annotation as Gedmo;
 
 
/**
 * @ORM\Entity(repositoryClass="App\Repository\ArticlesRepository")
 * @ORM\HasLifecycleCallbacks()
 * @Vich\Uploadable
 */
class Articles
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
 
    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\Length(
     *     min = 5,
     *     max = 255,
     *     minMessage = "le contenu de titre doit avoir au minimum {{ limit }} carctère",
     *     maxMessage = "le contenu de titre ne doit dépasser {{ limit }} carctère"
     * )
     */
    private $nameArticle;
 
    /**
     * @ORM\Column(type="text", nullable=false)
     * @Assert\Length(
     *     min = 50,
     *     minMessage = "le contenu de titre doit avoir au minimum {{ limit }} carctère",
     * )
     */
    private $articleContent;
 
    /**
     * @var \DateTime
     * @Gedmo\Timestampable(on="create")
     * @ORM\Column(name="created_at", type="datetime", nullable=false)
     */
    private $createdAt;
 
    /**
     * @var \DateTime
     * @Gedmo\Timestampable(on="update")
     * @ORM\Column(name="updated_at", type="datetime", nullable=false)
     */
    private $updatedAt;
 
    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="articles", cascade={"persist"})
     * @ORM\JoinColumn(nullable=false)
     */
    private $category;
 
    /**
     * NOTE: This is not a mapped field of entity metadata, just a simple property.
     *
     * @Vich\UploadableField(mapping="articles_image", fileNameProperty="imageName", size="imageSize")
     *
     * @var File
     */
    private $imageFile;
 
    /**
     * @ORM\Column(type="string", length=255)
     *
     * @var string
     */
    private $imageName;
 
    /**
     * @ORM\Column(type="integer")
     *
     * @var integer
     */
    private $imageSize;
 
    /**
     * @ORM\Column(type="text")
     */
    private $introduction;
 
    /**
     * @Gedmo\Slug(fields={"nameArticle"},separator="-", updatable=true, unique=true)
     * @ORM\Column(type="string", length=255)
     */
    private $slug;
 
    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Comments", mappedBy="articleComments")
     */
    private $comments;
 
 
    public function __construct()
    {
        $this->createdAt = new \DateTime("now", new \DateTimeZone('Europe/Paris'));
        $this->comments = new ArrayCollection();
    }
 
 
    public function getId()
    {
        return $this->id;
    }
 
    public function getNameArticle(): ?string
    {
        return $this->nameArticle;
    }
 
    public function setNameArticle(string $nameArticle): self
    {
        $this->nameArticle = $nameArticle;
 
        return $this;
    }
 
    public function getArticleContent(): ?string
    {
        return $this->articleContent;
    }
 
    public function setArticleContent(string $articleContent): self
    {
        $this->articleContent = $articleContent;
 
        return $this;
    }
 
    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }
 
    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
 
    public function getCategory(): ?Category
    {
        return $this->category;
    }
 
    public function setCategory(?Category $category): self
    {
        $this->category = $category;
 
        return $this;
    }
 
    /**
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
     * @throws \Exception
     */
    public function setImageFile(?File $image = null): void
    {
        $this->imageFile = $image;
 
        if (null !== $image) {
            // It is required that at least one field changes if you are using doctrine
            // otherwise the event listeners won't be called and the file is lost
            $this->updatedAt = new \DateTimeImmutable();
        }
    }
 
    public function getImageFile(): ?File
    {
        return $this->imageFile;
    }
 
    public function setImageName(?string $imageName): void
    {
        $this->imageName = $imageName;
    }
 
    public function getImageName(): ?string
    {
        return $this->imageName;
    }
 
    public function setImageSize(?int $imageSize): void
    {
        $this->imageSize = $imageSize;
    }
 
    public function getImageSize(): ?int
    {
        return $this->imageSize;
    }
 
    public function getIntroduction(): ?string
    {
        return $this->introduction;
    }
 
    public function setIntroduction(string $introduction): self
    {
        $this->introduction = $introduction;
 
        return $this;
    }
 
    public function getSlug(): ?string
    {
        return $this->slug;
    }
 
    public function setSlug(string $slug): self
    {
        $this->slug = $slug;
 
        return $this;
    }
 
    /**
     * @return Collection|Comments[]
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }
 
    public function addComment(Comments $comment): self
    {
        if (!$this->comments->contains($comment)) {
            $this->comments[] = $comment;
            $comment->setArticleComments($this);
        }
 
        return $this;
    }
 
    public function removeComment(Comments $comment): self
    {
        if ($this->comments->contains($comment)) {
            $this->comments->removeElement($comment);
            // set the owning side to null (unless already changed)
            if ($comment->getArticleComments() === $this) {
                $comment->setArticleComments(null);
            }
        }
 
        return $this;
    }
 
}

用户实体:

namespace App\Entity;
 
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Validator\Constraints as Assert;
 
/**
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @ORM\Table(name="fos_user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;
 
 
    /**
     * @Assert\Regex("/^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,}$/",
     *  message = "Votre mot de passe doit contenir minimum 6 carctère avec une miniscule majuscule un chiffre "
     * )
     *
     * @var string
     */
    //protected $password;
 
    /**
     * @Assert\Email(
     *     message = "l'adresse mail n'est pas valide"
     * )
     * @var string
     */
    protected $email;
 
 
    /**
     * @ORM\Column(type="string", length=255)
     * @var string
     */
    protected $age;
 
    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Comments", mappedBy="userComments", orphanRemoval=true)
     */
    private $comments;
 
    public function __construct()
    {
        parent::__construct();
        $this->comments = new ArrayCollection();
    }
 
 
    public function getAge(): ?string
    {
        return $this->age;
    }
 
    public function setAge(string $age): self
    {
        $this->age = $age;
 
        return $this;
    }
 
 
    /**
     * Place un rôle unique à l'utilisateur (supprimer tous les anciens rôles)
     * @param string $userRole
     */
    public function setRole(string $userRole)
    {
        // Vider les rôles
        foreach ($this->getRoles() as $role) {
            $this->removeRole($role);
        }
        // Ajout le rôle unique passé en paramètre
        $this->addRole($userRole);
    }
 
    /**
     * @return Collection|Comments[]
     */
    public function getComments(): Collection
    {
        return $this->comments;
    }
 
    public function addComment(Comments $comment): self
    {
        if (!$this->comments->contains($comment)) {
            $this->comments[] = $comment;
            $comment->setUserComments($this);
        }
 
        return $this;
    }
 
    public function removeComment(Comments $comment): self
    {
        if ($this->comments->contains($comment)) {
            $this->comments->removeElement($comment);
            // set the owning side to null (unless already changed)
            if ($comment->getUserComments() === $this) {
                $comment->setUserComments(null);
            }
        }
 
        return $this;
    }
}
php symfony doctrine
1个回答
3
投票

您不需要任何“自定义逻辑”代码,只需使用即可

// Articles.php

/**
 * @ORM\OneToMany(targetEntity="App\Entity\Comments", mappedBy="articleComments", cascade={"remove"})
 */
private $comments;

因此,当您删除article时,也会删除相关注释。

这个注释是一个ORM,所以它只适用于你的应用程序逻辑。如果你想把它也放在@DBMS级别,只需添加即可

@ORM\JoinColumn(name="comments_id", referencedColumnName="id", onDelete="CASCADE")

你会两个都有。

只是一个注意事项:从db表中创建复数名称并不常见。在我使用JoinColumn的例子中,我使用了comments(复数),但你必须验证名称是否与真实列名匹配,或者至少与你想要的名称相匹配。

回到你的问题,你要验证评论是否是null并尝试删除它。这里有很多错误:首先你是文章的路线,你正在用文章id作为主键搜索评论(所以在概念上是错误的)。

其次,您正在尝试删除null变量。

你可以在这里做的是摆脱该控制器的所有代码注释代码,并做这样的事情

/**
 * @Route("admin/supprimer/{id}")
 * @param int $id
 * @return Response
 */
 public function delete(int $id): Response {
   $article = $this->getDoctrine()
     ->getRepository(Articles::class)
     ->find($id);

   $manager = $this->getDoctrine()->getManager();

   foreach ($article->getComments() as $comment) {
     $manager->remove($comment);
   }

   $manager->remove($article);
   $manager->flush();

   $this->addFlash('deleteArticle', 'L\'article a bien étais supprimer');

   return $this->redirectToRoute('app_backoffice_admin');
 }

最后,但并非最不重要的是,您可以直接为Article键入提示,它将由Symfony ParamConvert解决

/**
 * @Route("admin/supprimer/{id}")
 * @param int $id
 * @return Response
 */
 public function delete(Article $article): Response {
   $manager = $this->getDoctrine()->getManager();

   foreach ($article->getComments() as $comment) {
     $manager->remove($comment);
   }

   $manager->remove($article);
   $manager->flush();

   $this->addFlash('deleteArticle', 'L\'article a bien étais supprimer');

   return $this->redirectToRoute('app_backoffice_admin');
 }
© www.soinside.com 2019 - 2024. All rights reserved.