我使用 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:prePersist
和 ProjectsAdmin: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/