symfony - Doctrine 不会在我的 OneToMany 关联中保存数据

标签 symfony doctrine-orm doctrine associations sonata-admin

我使用 Symfony 4 和 Sonata Admin。我有一个项目多个新闻协会。 我在尝试在项目管理页面添加一些新闻并更新项目时发现了一个问题。问题是新闻尚未添加到项目中。然后我通过将以下代码添加到我的 ProjectsAdmin.php 文件中解决了这个问题:

 public function prePersist($project)
    {
        $this->preUpdate($project);
    }

    public function preUpdate($project)
    {
        $project->setNews($project->getNews());
    }

但是仍然存在一些问题。第二个是我无法从项目中删除新闻,单击更新按钮后没有任何反应。当然,如果我在项目实体中使用“orphanRemoval=true”来获取现场新闻,它会起作用,但它会删除我只想从项目中删除的新闻。 我该如何解决这个问题?

最后但并非最不重要的一点是,我有 PreUpdate 事件监听器来检查:是否更新项目实体而不是向该项目添加所有新闻。问题是,当我对项目实体执行此操作时,它不起作用,但当我对新闻实体执行相同操作时,它会起作用。我忘了提及,它与我在管理面板中的问题非常相似,因为当我转到新闻管理并尝试将项目添加到新闻时,它无需任何修复即可工作,当我尝试从新闻管理中的新闻中删除项目时,它也可以按预期工作。因此,在 inversedBy 方面一切正常,但在mappedBy 方面我遇到了问题。

这是我的事件监听器:

 public function PreUpdate(LifecycleEventArgs $args): void {
        $entity = $args->getEntity();
        $newsRepo = $args->getEntityManager()->getRepository(News::class);
        if ($entity instanceof Projects) {
            foreach ($newsRepo as $new){
                $news = $args->getEntityManager()->getReference(News::class, $new->getId());
                $entity->setNews($news);
            }
        }
    }

我的项目实体:

/**
 * @ORM\Entity(repositoryClass=ProjectsRepository::class)
 * @ORM\HasLifecycleCallbacks()
 */
class Projects {
   /**
     * @ORM\OneToMany(targetEntity=News::class, mappedBy="project", orphanRemoval=true)
     */
    private $news;

    public function __construct() {
        $this->news = new ArrayCollection();
    }
  
      /**
     * @return Collection|News[]
     */
    public function getNews(): Collection {
        return $this->news;
    }

    /**
     * @param mixed $news
     * @return Projects
     */
    public function setNews($news) {
        if (count($news) > 0) {
            foreach ($news as $i) {
                $this->addNews($i);
            }
        }
        return $this;
    }

    /**
     * @param News $news
     */
    public function addNews(News $news) {
        $news->setProject($this);
        $this->news->add($news);
    }

    /**
     * @param News $news
     */
    public function removeNews(News $news) {
        $this->news->removeElement($news);
    }
}

新闻实体:

/**
 * @ORM\Entity(repositoryClass="App\Repository\NewsRepository")
 * @ORM\HasLifecycleCallbacks()
 */
class News {
    /**
     * @ORM\ManyToOne(targetEntity=Projects::class, inversedBy="news")
     * @ORM\JoinColumn(nullable=true)
     */
    private $project;

    public function getProject(): ?Projects {
        return $this->project;
    }

    public function setProject(?Projects $project): self {
        $this->project = $project;

        return $this;
    }
}

项目存储库:

/**
 * @method Projects|null find($id, $lockMode = null, $lockVersion = null)
 * @method Projects|null findOneBy(array $criteria, array $orderBy = null)
 * @method Projects[]    findAll()
 * @method Projects[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class ProjectsRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, Projects::class);
    }
}

新闻库:

/**
 * @method News|null find($id, $lockMode = null, $lockVersion = null)
 * @method News|null findOneBy(array $criteria, array $orderBy = null)
 * @method News[]    findAll()
 * @method News[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class NewsRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, News::class);
    }
}

最佳答案

首先,您的 ProjectsAdmin:prePersistProjectsAdmin:preUpdate 方法似乎没有完成任何任务。其次,您的事件监听器看起来也不正确。我不认为任何这些代码都是必要的,因为您应该能够在实体级别解决这个问题。

NewsAdmin 中一切按预期工作的原因是 News 是关系的拥有方,因此当您从 Projects 端还必须调用 News 端的相应方法。另外,您说您能够成功地将 News 项目添加到 Projects 但无法删除它们,因此,让我们将您的 Projects:addNews 方法与您的方法进行比较Projects:removeNews 方法。您将看到工作 Projects:addNews 方法影响拥有 News 端的更改,而非工作 Projects:removeNews 方法仅作用于 Projects 端。您只需修改 Projects:removeNews 即可将 News:project 属性设置为 null

/**
 * @param News $news
 */
public function addNews(News $news) {
    // next line makes this work
    $news->setProject($this);
    $this->news->add($news);
}

/**
 * @param News $news
 */
public function removeNews(News $news) {
    // make this work the same way with next line
    $news->setProject(null);
    $this->news->removeElement($news);
}

关于symfony - Doctrine 不会在我的 OneToMany 关联中保存数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66695050/

相关文章:

symfony - 从一个存储库到另一个存储库的Symfony大量 hydration

php - 如何处理 Doctrine 2 验证的异常

symfony - 如何使用 Doctrine ArrayCollection 的 forAll 方法?

php - JMS 序列化 @VirtualProperty 不起作用

php - Symfony 3 表单类型错误

php - Symfony3 可捕获 fatal error : Argument 1 passed to Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationProvider

php - 在 Symfony 中使用 config.php 和 doctrine.yaml 使用动态数据库名称

orm - 是否可以在没有目标实体的情况下在 Doctrine2 中建立关联?

javascript - 如何将数据值传递给jquery函数

php - Doctrine mysql,检查数组是否在其他数组中