【问题标题】:Symfony 3.4 Duplication of my User object in databaseSymfony 3.4 我的用户对象在数据库中的重复
【发布时间】:2019-04-16 11:51:11
【问题描述】:

我有一个很奇怪的问题。使用 CAS 身份验证,当我有用户登录时,会检查数据库以返回相应的 User 对象(其中包含一些属性)。

除其他外,User 实体包含 Package(实体)ManyToMany 的 ArrayCollection()。

然后,该用户可以下载软件包。 当它下载一个时,包被添加到它的 ArrayCollection() 中(所以我在 User 和 Packag 之间的关联表中有一个新行,带有 User 的 id 和包的 id)。

除了奇怪的是,我无法正确处理 User 实体,因为当我有一个下载包时,数据库中的整个 User 对象都有重复,这就是添加包的好处在它的ArrayCollection()中。

简而言之,我的用户对象在页面之间没有正确传递。

我的代码:

当用户认证时(CAS认证):

/**
     * Traitement personnalisé après récupération du token
     * 
     * Il est possible d'enrichir le token (attributs...) ou d'effectuer des contrôles supplémentaire
     * 
     * @param $token 
     *      Token d'authification généré
     * 
     * @return null
     */
    public function onSuccess($token){

        $mail = $this->ai->getMail();

        $token->setAttribute('mail', $mail);;   
        $token->setAttribute('typeAuth','cas');

        $user = $this->checkBDD($mail);
        $user = $this->serializer->serialize($user, 'json');

        $token->setAttribute('user',$user);

        

       // $user = $this->checkBDD($mail);
       // $token->setAttribute('user',$user);

    }

所以我们得到了与之关联的用户对象(或者如果它是第一次连接,我们创建一个)。

/**
 * Vérifie si l'utilisateur CAS existe et le crée sinon et renvoi l'objet
 * 
 * @return UserCas
 */
public function checkBDD($mail)
{
    $nb = $this->em->getRepository('PagesBundle:UserCas')->getIfUserCas($mail);

    if($nb == 0)
    {
        //création

        $user = new UserCas;

        $nbPackages = $this->em->getRepository('PagesBundle:Paquet')->getNombrePackages();

        $user->setMail($mail);
        $user->setNbTelechargementsAuto($nbPackages);
        $this->em->persist($user);
        $this->em->flush();
    }

    else
    {
        $user = $this->em->getRepository('PagesBundle:UserCas')->findOneByMail($mail);
    }

    return $user;

    }

User 对象随后被序列化并作为令牌中的属性传递。

然后他可以访问“包”选项卡,他可以在其中下载包及其说明。 如果它下载了一个包,那么我们将这个包添加到它的 ArrayCollection 中。

/** 
     * Lorsque l'on clique sur un package à télécharger ou sa notice : Téléchargement
     *
     * @Route("/{id}/{type}/file", name="user_paquet_fileDDL")
     */
    public function paquetFileAction(Paquet $paquet, $type)
    {
        $downloadHandler = $this->get('vich_uploader.download_handler'); // On prépare le téléchargement

        if($type == "package") //Si l'utilisateur clique sur le lien du package, on lui donne le fichier package
        {
            $token = $this->get('security.token_storage')->getToken();
            $typeAuth = $token->getAttribute('typeAuth');

            if($typeAuth == 'cas')
            {
                $user = $token->getAttribute('user');
                $user = $this->get('serializer')->deserialize($user, 'Site\PagesBundle\Entity\UserCas', 'json');
            }

            else
            {
                $em = $this->getDoctrine()->getManager(); //Récupération du manager
                //$this->getDoctrine()->getManager()->getRepository('PagesBundle:User')->setDDL("test"); //On décrémente le nombre de DDL pour l'utilisateur en question
                $user = $this->getUser();
            }

            $this->packageDDL($paquet,$user);

            return $downloadHandler->downloadObject($paquet, $fileField = 'paquetFile', Paquet::class, null);
        }

        else //Sinon c'est qu'il a cliqué sur le lien de la notice, alors on lui donne la notice associée au package
        {
            return $downloadHandler->downloadObject($paquet, $fileField = 'noticeFile', Paquet::class, null);
        }
        
    }

使用此功能:

public function packageDDL($paquet,$user)
    {
        $token = $this->get('security.token_storage')->getToken();
        $typeAuth = $token->getAttribute('typeAuth');

        $em = $this->getDoctrine()->getManager(); //Récupération du manager
        $user->addPackage($paquet);
        $em->persist($user);
        $em->flush();

        if($typeAuth == 'cas')
        {
            $data = $this->get('serializer')->serialize($user, 'json');
            $token->setAttribute('user',$data) ;
        }
    }

它调用一个 Trait 上的 addPackage($paquet) 函数。

public function addPackage($package)
{
    $this->packages[] = $package;
    $this->decDDL();
    
}

当完成并保存(持久化、刷新)后,我们重新序列化用户对象并将其放回令牌中。 好吧,它会创建一个新用户。

我的用户实体的一部分:

/**  
 * @var \Doctrine\Common\Collections\Collection
 * @ORM\ManyToMany(targetEntity="Paquet")  
 * @ORM\JoinTable(name="paquetsDDLUserCas") 
 * @ORM\JoinColumn(nullable=false)
 */  
private $packages;

/**
 * Constructor
 */
public function __construct()
{
    $this->packages = new ArrayCollection();
    $this->setEnabled(true);

}

怎么了?我不明白

编辑:

我删除了我的用户的序列化。现在效果更好了。但是现在,当我下载一个包时,我有这个:

Image

我的文件未下载,但我的数据库已编辑!

UserCas.php:

<?php

namespace Site\PagesBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Site\PagesBundle\Security\Traits\traitUser;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * UserCas
 *
 * @ORM\Table(name="user_cas")
 * @ORM\Entity(repositoryClass="Site\PagesBundle\Repository\UserCasRepository")
 * @UniqueEntity("mail")
 */
class UserCas
{

    use traitUser;

    
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var int
     *
     * @ORM\Column(name="nbTelechargementsAuto", type="integer", nullable=true)
     */
    private $nbTelechargementsAuto;

    /**
     * @var bool
     *
     * @ORM\Column(name="enabled", type="boolean")
     */
    private $enabled;


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

    /**  
     * @var \Doctrine\Common\Collections\Collection
     * @ORM\ManyToMany(targetEntity="Paquet")  
     * @ORM\JoinTable(name="paquetsDDLUserCas") 
     * @ORM\JoinColumn(nullable=false)
     */  
    private $packages;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->packages = new ArrayCollection();
        $this->setEnabled(true);

    }




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


    /**
     * @return string
     */
    public function getMail()
    {
        return $this->mail;
    }

    public function setMail($mail)
    {
        $this->mail = $mail;
    }

    
    /**
     * Set enabled
     *
     * @param boolean $enabled
     *
     * @return UserCas
     */
    public function setEnabled($enabled)
    {
        $this->enabled = $enabled;

        return $this;
    }

    public function isEnabled()
    {
        return $this->enabled;
    }

}

Paquet.php:

<?php

namespace Site\PagesBundle\Entity;

use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Site\PagesBundle\Entity\Paquet;
use Site\PagesBundle\Entity\TypeUser;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\Common\Collections\ArrayCollection;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * 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;
    }


    /**
     * @var string
     *
     * @ORM\Column(name="titre", type="string", length=255)
     * @Assert\Length(min=5, max=255, minMessage="Le titre doit comporter au minimum 5 caractères")
     */
    private $titre;

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

    /**
     * @Vich\UploadableField(mapping="paquet", fileNameProperty="urlPaquet")
     * @var File
     */
    private $paquetFile;

    /**
     * @ORM\Column(type="datetime")
     *
     * @var \DateTime
    */
    private $updatedAt;

    /**
 * @param File|UploadedFile $unPaquetFile
 *
 * @return Paquet
*/
public function setPaquetFile(File $unPaquetFile = null)
{
    $this->paquetFile = $unPaquetFile;

    if ($unPaquetFile) 
    {
        $this->updatedAt = new \DateTimeImmutable();
    }
        
    
    return $this;
}

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     *
     * @return Paquet
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

/**
 * @return File|null
 */
public function getPaquetFile()
{
    return $this->paquetFile;
}


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

    /**
     * @Vich\UploadableField(mapping="notice", fileNameProperty="urlNotice",nullable=true)
     * @var File
     */
    private $noticeFile;

    /**
     * @var string
     *
     * @ORM\Column(name="commentaire", type="text")
     */
    private $commentaire;


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

    /**
     * Set titre
     *
     * @param string $titre
     *
     * @return Paquet
     */
    public function setTitre($titre)
    {
        $this->titre = $titre;

        return $this;
    }

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

    /**
     * Set urlPaquet
     *
     * @param string $urlPaquet
     *
     * @return Paquet
     */
    public function setUrlPaquet($urlPaquet)
    {
        $this->urlPaquet = $urlPaquet;

        return $this;
    }

    /**
     * Get urlPaquet
     *
     * @return string|null
     */
    public function getUrlPaquet()
    {
        return $this->urlPaquet;
    }

    /**
     * @return File|null
     */
    public function getNoticeFile()
    {
        return $this->noticeFile;
    }

        /**
     * @param File|UploadedFile $uneNoticeFile
     *
     * @return Paquet
    */
    public function setNoticeFile(File $uneNoticeFile = null)
    {
        $this->noticeFile = $uneNoticeFile;

        if ($uneNoticeFile) 
        {
            $this->updatedAt = new \DateTimeImmutable();
        }
        
    
        return $this;
}

    /**
     * Set urlNotice
     *
     * @param string $urlNotice
     *
     * @return Paquet
     */
    public function setUrlNotice($urlNotice)
    {
        $this->urlNotice = $urlNotice;

        return $this;
    }

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

    /**
     * Set commentaire
     *
     * @param string $commentaire
     *
     * @return Paquet
     */
    public function setCommentaire($commentaire)
    {
        $this->commentaire = $commentaire;

        return $this;
    }

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

在删除所有序列化之后,我的方法中有:

public function packageDDL($paquet,$user)
    {
        $token = $this->get('security.token_storage')->getToken();
        $typeAuth = $token->getAttribute('typeAuth');

        dump($user);
        $em = $this->getDoctrine()->getManager(); //Récupération du manager
        $user->addPackage($paquet);
        $em->persist($user);
        $em->flush();

        if($typeAuth == 'cas')
        {
            $data = $this->get('serializer')->serialize($user, 'json');
            $token->setAttribute('user',$data) ;
        }
    }

【问题讨论】:

  • checkBDD函数中,你有没有检查过$nb不会一直返回0
  • 是的,我看过了。第一次,$nb 为 0,并创建了一个用户。而如果我更新,则等于1,并且没有创建额外的用户
  • 如何使用 $user->addPackage($paquet);如果您的用户实体中没有定义这样的功能?
  • 具有特质。我的 addPackage() 函数属于 Trait ^^
  • 这个特征是否正确?因为从方法 addPackage 向用户添加包应该没有任何问题?您的方法应如下所示: public function addPackage(Package $package): self { if (!$this->packages->contains($package)) { $this->packages[] = $package; //如果 ManyToMany 在两边就取消注释 //$package->setUser($this); } 返回 $this; }

标签: php database symfony


【解决方案1】:

你的问题是

$em->persist($user);

在你的 packageDDL 函数中

您不需要保留实体用户,因为它已经存在。 你只是想冲洗它。所以只需修改你的函数:

public function packageDDL($paquet,$user)
    {
        $token = $this->get('security.token_storage')->getToken();
        $typeAuth = $token->getAttribute('typeAuth');

        $em = $this->getDoctrine()->getManager(); //Récupération du manager
        $user->addPackage($paquet);
        $em->flush();

        if($typeAuth == 'cas')
        {
            $data = $this->get('serializer')->serialize($user, 'json');
            $token->setAttribute('user',$data) ;
        }
    }

【讨论】:

  • 通过删除这一行,我可以下载文件并且不再有用户重复。但是,我的数据库不再受到影响,该包没有添加到我的用户的那些。而且我还注意到,由于我的 $ 用户在反序列化后转储了 ID 已传递给 null
  • 我可以看看你的用户和包实体吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-28
  • 2018-05-29
  • 2016-10-26
  • 2019-08-10
  • 1970-01-01
  • 2021-05-25
相关资源
最近更新 更多