Symfony 多对多重复条目

Symfony ManyToMany duplicate entry

当我想插入具有 ManyToMany 关系的数据时遇到问题。

当我想使用我的 CategoryType 创建一个新类别时,我只需要名称字段。 在我的 AdminCategoryController 中,我想通过获取我工作的域服务器来强制一个站点。

更新 事实上,我有很多站点和很多域。所有站点都必须使用他的服务器名连接到一个唯一的数据库。 所以我的 VHOST 是为此配置的。

所以,我有 2 个实体:网站、类别

站点实体 :

<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\SiteRepository")
 */
class Site
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $domain;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Category", mappedBy="site")
     */
    private $categories;

    public function __construct()
    {
        $this->categories = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getDomain(): ?string
    {
        return $this->domain;
    }

    public function setDomain(string $domain): self
    {
        $this->domain = $domain;

        return $this;
    }

    /**
     * @return Collection|Category[]
     */
    public function getCategories(): Collection
    {
        return $this->categories;
    }

    public function addCategory(Category $category): self
    {
        if (!$this->categories->contains($category)) {
            $category->addSite($this);
            $this->categories[] = $category;
        }

        return $this;
    }

    public function removeCategory(Category $category): self
    {
        if ($this->categories->contains($category)) {
            $this->categories->removeElement($category);
            $category->removeSite($this);
        }

        return $this;
    }
}

类别实体:

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\CategoryRepository")
 */
class Category
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $name;

    /**
     * @ORM\ManyToMany(targetEntity="App\Entity\Site", inversedBy="categories", cascade={"persist"})
     */
    private $site;

    public function __toString(){
        return $this->name;
    }

    public function __construct(Site $site)
    {
        $this->site = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return Collection|Site[]
     */
    public function getSite(): Collection
    {
        return $this->site;
    }

    public function addSite(Site $site): self
    {
        if (!$this->site->contains($site)) {
            $this->site[] = $site;
        }

        return $this;
    }

    public function removeSite(Site $site): self
    {
        if ($this->site->contains($site)) {
            $this->site->removeElement($site);
        }

        return $this;
    }
}

我通过会话在 SiteService 中获取站点信息:

use App\Repository\SiteRepository;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class SiteService{

    public $infos;

    private $session;
    private $requestStack;

    private $siteRepository;

    public function __construct(SessionInterface $session, RequestStack $requestStack, SiteRepository $siteRepository){
        $this->session = $session;
        $this->requestStack = $requestStack;
        $this->siteRepository = $siteRepository;

        $this->getInfos();
    }

    public function getInfos(){
        $this->infos = $this->session->get('site');
        if(empty($this->infos)){
            $request = $this->requestStack->getCurrentRequest();
            $server_name = $request->server->get('SERVER_NAME');
            $this->infos = $this->siteRepository->findOneBy(['domain'=>$server_name]);
            if($this->infos == NULL){
                $this->infos = $this->siteRepository->findOneBy([]);
            }
            $this->session->set('site', $this->infos);
            $this->infos = $this->session->get('site');
        }
        return $this->infos;
    }
}

这是我的 CategoryController,用于在站点中添加新类别

 /**
 * @Route("/new", name="admin.category.new")
 * @param  Request $request
 * @return Response
 */
public function new(Request $request):Response{
    $category = new Category();

    $form = $this->createForm(CategoryType::class, $category);
    $form->handleRequest($request);

    $server_name = $request->server->get('SERVER_NAME');
    $site = $this->siteRepository->findBy(['domain'=>$server_name]);

    $siteFromSession = $this->session->get('site');

    if($form->isSubmitted() && $form->isValid()){
        $category->addSite($site);
        $this->em->persist($category);
        $this->em->flush();

        return $this->redirectToRoute('admin.category.edit', ['id'=>$category->getId()]);
    }

    $form = $form->createView();
    $params = compact('category', 'form');
    return $this->render('admin/category/new.html.twig', $params);
}

两个变量转储不相等..

dump($site);

Site {#187 ▼
  -id: 1
  -name: "My Website"

转储($siteFromSession);

Site {#623 ▼
  -id: 1
  -name: "My Website"

如果我使用 $category->addSite($site); 坚持类别 上班了。

但是当我使用 $category->addSite($siteFromSession); 坚持类别时 我在我的数据库中看到当前站点在站点 table 中是重复的并且 category.site 是新站点,而不是我插入的站点。

但是,我不想在每次添加类别时都执行查询。 我只想在第一次登录管理页面时使用会话来获取站点的信息

感谢帮助我

太棒了!!我解决了! 当我想在会话中保存站点信息时,我将其分离,当我想从会话中获取实体时,我将其合并

public function setInfos(){
    $request = $this->requestStack->getCurrentRequest();
    $server_name = $request->server->get('HTTP_HOST');
    $site = $this->siteRepository->findOneBy(['domain'=>$server_name]);
    $this->em->detach($site);
    $this->session->set('site', $site);
}

public function getInfos()
    $site = $this->session->get('site');
    $site = $this->em->merge($site);
}