Symfony 3 - проблема ManyToMany с моими сущностями - PullRequest
3 голосов
/ 06 мая 2019

У меня странная проблема в Symfony 3.4

Я проясняю ситуацию: у меня есть две сущности:

UserType и Package .Цель состоит в том, чтобы предлагать пакеты моим пользователям в зависимости от их типа (пользователи будут видеть пакеты, соответствующие их типу пользователя).

Пакет может принадлежать более чем одному типу пользователя, и тип пользователя можету меня несколько пакетов.

Итак, у меня есть отношение ManyToMany.

TypeUser.php

namespace Site\PagesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * TypeUser
 *
 * @ORM\Table(name="type_user")
 * @ORM\Entity(repositoryClass="Site\PagesBundle\Repository\TypeUserRepository")
 */
class TypeUser
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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


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

    /**
     * Set typeUtilisateur
     *
     * @param string $typeUtilisateur
     *
     * @return TypeUser
     */
    public function setTypeUtilisateur($typeUtilisateur)
    {
        $this->typeUtilisateur = $typeUtilisateur;

        return $this;
    }

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

Paquet.php:

<?php
namespace Site\PagesBundle\Entity;
//use
/**
 * Paquet
 *
 * @ORM\Table(name="paquet")
 * @ORM\Entity(repositoryClass="Site\PagesBundle\Repository\PaquetRepository")
 * @Vich\Uploadable
 */
class Paquet
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**  
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\ManyToMany(targetEntity="TypeUser")  
     * @ORM\JoinTable(name="Packages_des_TypesUser") 
     * @ORM\JoinColumn(nullable=false)
     */  
    private $typeUser;
    public function __construct()
    {
        $this->typeUser = new ArrayCollection();
    }
    /** 
     * Get TypeUser 
     * 
     * @return Site\PagesBundle\Entity\TypeUser 
     */ 
    public function getTypeUser() 
    { 
        return $this->typeUser; 
    }
    public function deleteTypeFromTypesUser(TypeUser $type)
    {
        $this->typeUser->removeElement($type);
    }
    /**
     * Set typeUser
     *
     * @param Site\PagesBundle\Entity\TypeUser $typeUser
     *
     * @return Paquet
     */
    public function setTypeUser(Site\PagesBundle\Entity\TypeUser $typeUser)
    {
        $this->typeUser = $typeUser;
        return $this;
    }
    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
}

Итак, когда я добавляю пакет, я могу выбрать пользователя TypeUser:

enter image description here

А когда я управляю пакетами:

enter image description here

Теперь, если я хочу изменить пакет, добавив тип пользователя, возникнет проблема:

У меня естьпакет: Давайте добавим нового TypeUser, нажав на «Модификатор»

enter image description here

Давайте проверим «DAFPIC»:

enter image description here

Хорошо, у меня есть пакет, который тоже есть в DAFPIC, с новой строкой в ​​моей ассоциации в базе данных:

enter image description here enter image description here

Но теперь, еслиЯ нажимаю «Supprimer» в новом пакете DAFPIC, и, если я дам дамп TypeUser этого пакета, я получу первого пользователя typeUser:

enter image description here

Итак, яне понимаю, в чём дело ... Может кто-нибудь помочь мне, пожалуйста?

РЕДАКТИРОВАТЬ:

Когда я нажимаю кнопку удаления:

/**
     * Suppression d'un package | Suppression d'un type d'utilisateur attribué à un package
     *
     * @Route("/{id}/{type}/delete", name="paquets_delete")
     */
    public function deleteAction(Request $request, $id, $type)
    {
        $em = $this->getDoctrine()->getManager();
        $unPaquet = $em->getRepository('PagesBundle:Paquet')->find($id); //Récupération du package
        $leType = $em->getRepository('PagesBundle:TypeUser')->findOneByTypeUtilisateur($type);
        dump($leType);

        $em->remove($unPaquet);

        return $this->redirectToRoute('paquets_index'); // Actualisation de la page
}

РЕДАКТИРОВАТЬ: взятьпосмотрите на мою схему:

enter image description here

1 Ответ

1 голос
/ 06 мая 2019

Кажется, вы удаляете пакет, а не связанный UserTypePaquet между Paquet и UserType.

USER_TYPE <== USER_TYPE_PAQUET ==> PAQUET.
                    ^^               ^^
                    ||               ||
                    ||               ||
          you should delete this     ||
                                     ||
              you are currently deleting this 

(и вы наверняка удаляете также все ассоциации с пакетами)

Вы должны выбрать все пакеты, связанные с этим пользователем (вызвав коллекцию с помощью getPaquets ()), и удалить один элемент, соответствующий пакет.

    /**
     * Suppression d'un package | Suppression d'un type d'utilisateur attribué à un package
     *
     * @Route("/{id}/{type}/delete", name="paquets_delete")
     */
    public function deleteAction(Request $request, $id, $type)
    {
        $em = $this->getDoctrine()->getManager();
        $unPaquet = $em->getRepository('PagesBundle:Paquet')->find($id); //Récupération du package
        $leType = $em->getRepository('PagesBundle:TypeUser')->findOneByTypeUtilisateur($type);
        dump($leType);

        //$em->remove($unPaquet); <=== DO NOT remove THE PAQUET
        $leType->getPaquets()->remove($unPaquet);// <=== Remove only the paquet associated to user
        $em->persist($leType); //Then save $leType sans le paquet associé
        $em->flush();

        return $this->redirectToRoute('paquets_index'); // Actualisation de la page
    }

Это решение - первый шаг к решению вашей проблемы. Теперь вам нужно удалить использование сущностей PaquetDDLCas. У вас есть два решения: первое (тем лучше) - слишком обновить схему базы данных, чтобы добавить ограничение «при удалении каскада» между PaquetDDLCas для внешнего ключа, связывающего PaquetDDLCas с PackageTypeUser.

ALTER TABLE PaquetDDLCas ADD CONSTRAINT FK_xxxx FOREIGN KEY (paquet_id, type_user_id) REFERENCES Package_typeuser (paquet_id, type_user_id) ON DELETE CASCADE')

Если вы правильно связываете PaquetDDLCas с PaquetTypeUser (и удаляете две ваши ссылки, одну на Paquet, другую на PaquetTypeUser) и проверяете атрибут доктрины-сироты на «да», этот код будет сгенерирован доктриной.

Второй метод состоит в том, чтобы сделать это вручную и вызвать ваш PaquetDDLCasRepository и создать новую функцию, которая удалит все данные.


public function deleteByPaquetAndTypeUser($paquet,$user)
{
    $qb = $this->createQueryBuilder('p')
    $qb->delete()
       ->where('p.user = :user')
       ->andWhere('p.paquet = :paquet')
       ->setParameter('user', $user)
       ->setParameter('paquet', $paquet)
       ->getQuery()
       ->getResult();
}

Но этот метод не является хорошей практикой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...