使用 symfony 请求 2 个表的问题

problem with a request on 2 tables with symfony

我试图通过条令请求获取存储在 message_document table 中的消息的文档,但请求循环并最终填满了我的记忆 我在 Dbeaver 上用 sql 尝试了相同的请求,它运行没有问题

非常感谢您的帮助

我的message.php

enter code here

namespace App\Entity;

use DateTime;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\MessageRepository;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass=MessageRepository::class)
 */
class Message
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="text")
     */
    private $content;

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
    * @ORM\ManyToOne(targetEntity=Conversation::class, inversedBy="messages")
    */
    private $conversation; 

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="messages")
     */
    private $user;

    /**
     * @ORM\OneToMany(targetEntity=MessageDocument::class, mappedBy="messages")
     */
    private $messageDocuments;


    public function __construct( string $content, User $user, Conversation $converstation) {
        $this->content      = $content;
        $this->user         = $user;
        $this->conversation = $converstation;
        $this->createdAt    = new \DateTime('now');
        $this->messageDocuments = new ArrayCollection();
    }

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

    public function getContent():?string {
        return $this->content;
    }
    public function setContent(string $content):self {
        $this->content = $content;
        return $this;
    }

    public function getCreatedAt():?\DateTimeInterface {
        return $this->createdAt;
    }
    public function setCreatedAt(\DateTimeInterface $createdAt):self {
        $this->createdAt = $createdAt;
        return $this;
    }
    
    public function getConversation():?Conversation
    {
        return $this->conversation;
    }
    public function setConversation(?Conversation $conversation):self {
        $this->conversation = $conversation;
        return $this;
    }

    public function getUser():?User {
        return $this->user;
    }
    public function setUser(?User $user):self {
        $this->user = $user;
        return $this;
    }

    /**
     * @return Collection|MessageDocument[]
     */
    public function getMessageDocuments(): Collection
    {
        return $this->messageDocuments;
    }

    public function addMessageDocument(MessageDocument $messageDocument): self
    {
        if (!$this->messageDocuments->contains($messageDocument)) {
            $this->messageDocuments[] = $messageDocument;
            $messageDocument->setMessages($this);
        }

        return $this;
    }

    public function removeMessageDocument(MessageDocument $messageDocument): self
    {
        if ($this->messageDocuments->removeElement($messageDocument)) {
            // set the owning side to null (unless already changed)
            if ($messageDocument->getMessages() === $this) {
                $messageDocument->setMessages(null);
            }
        }

        return $this;
    }

    
}

我的MessageDocument.php

enter code here

namespace App\Entity;

use App\Repository\MessageDocumentRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=MessageDocumentRepository::class)
 */
class MessageDocument
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

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

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

    /**
     * @ORM\ManyToOne(targetEntity=Message::class, inversedBy="messageDocuments")
     */
    private $message;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="messageDocuments")
     */
    private $sender;

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

    public function getFileName(): ?string
    {
        return $this->fileName;
    }

    public function setFileName(string $fileName): self
    {
        $this->fileName = $fileName;

        return $this;
    }

    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(\DateTimeInterface $updatedAt): self
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    public function getType(): ?string
    {
        return $this->type;
    }

    public function setType(?string $type): self
    {
        $this->type = $type;

        return $this;
    }

    public function getMessage(): ?Message
    {
        return $this->message;
    }

    public function setMessage(?Message $message): self
    {
        $this->message = $message;

        return $this;
    }

    public function getSender(): ?User
    {
        return $this->sender;
    }

    public function setSender(?User $sender): self
    {
        $this->sender = $sender;

        return $this;
    }
}

MessageDocument 加入消息的请求

/**
*  @return MessageDocument[] Returns an array of MessageDocument objects
*/
 //$qb->expr()->eq('md.id = :val')
//,Join::WITH,$qb->expr()->eq('md.id = :val') 
public function findDocByMessageId($messageId)
{
    return $this->createQueryBuilder('md')
        ->select('md')
        ->join('md.message','m')        
        ->where('m.id =:val')
        ->setParameter('val', $messageId)
        ->setMaxResults(20)
        ->getQuery()    
        ->getResult();
}

回购请求的调用

$allMessages = new ArrayCollection();
    $docs=[];
    foreach ($messages as $messageUnique) {
        $messId = $messageUnique->getId();
        $documentsMessages = $messageRepository->findDocByMessageId($messId);

        if($documentsMessages !== null){
            foreach($documentsMessages as $document){
                $docs=$document;
            }
                //$messageUnique->addMessageDocument($document);
        }

        $conversation->setLastMessage($messageUnique);
        
        $messageUnique = array(
            'id'        => $messageUnique->getId(),
            'author'    => $messageUnique->getUser()->getFullName(),
            'authorId'  => $messageUnique->getUser()->getId(),
            'content'   => $messageUnique->getContent(),
            'createdAt' => $messageUnique->getCreatedAt()
        );
        $allMessages->add($messageUnique);

    }

我完全不确定如何将 $messageUnique = array() 设置为同一个变量的值,您可能应该使用另一个变量名称。如果你有一个无限循环问题,它来自你的 PHP。

我更改了我的代码,现在错误消息是关于循环引用的

消息实体

namespace App\Entity;

use DateTime;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use App\Repository\MessageRepository;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @ORM\Entity(repositoryClass=MessageRepository::class)
 */
class Message
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="text")
     */
    private $content;

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    /**
    * @ORM\ManyToOne(targetEntity=Conversation::class, inversedBy="messages")
    */
    private $conversation; 

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="messages")
     */
    private $user;

    /**
     * @ORM\OneToMany(targetEntity=MessageDocument::class, mappedBy="message")
     */
    private $messageDocument;


    public function __construct( string $content, User $user, Conversation $converstation) {
        $this->content      = $content;
        $this->user         = $user;
        $this->conversation = $converstation;
        $this->createdAt    = new \DateTime('now');
        $this->messageDocuments = new ArrayCollection();
    }

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

    public function getContent():?string {
        return $this->content;
    }
    public function setContent(string $content):self {
        $this->content = $content;
        return $this;
    }

    public function getCreatedAt():?\DateTimeInterface {
        return $this->createdAt;
    }
    public function setCreatedAt(\DateTimeInterface $createdAt):self {
        $this->createdAt = $createdAt;
        return $this;
    }
    
    public function getConversation():?Conversation
    {
        return $this->conversation;
    }
    public function setConversation(?Conversation $conversation):self {
        $this->conversation = $conversation;
        return $this;
    }

    public function getUser():?User {
        return $this->user;
    }
    public function setUser(?User $user):self {
        $this->user = $user;
        return $this;
    }

    /**
     * @return Collection|MessageDocument[]
     */
    public function getMessageDocument(): Collection
    {
        return $this->messageDocument;
    }

    public function addMessageDocument(MessageDocument $messageDocument): self
    {
        if (!$this->messageDocument->contains($messageDocument)) {
            $this->messageDocument[] = $messageDocument;
            $messageDocument->setMessages($this);
        }

        return $this;
    }

    public function removeMessageDocument(MessageDocument $messageDocument): self
    {
        if ($this->messageDocuments->removeElement($messageDocument)) {
            // set the owning side to null (unless already changed)
            if ($messageDocument->getMessages() === $this) {
                $messageDocument->setMessages(null);
            }
        }

        return $this;
    }

    
}

MessageDocument 实体

<?php

namespace App\Entity;

use App\Repository\MessageDocumentRepository;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=MessageDocumentRepository::class)
 */
class MessageDocument
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

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

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

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

    /**
     * @ORM\ManyToOne(targetEntity=Message::class, inversedBy="messageDocument")
     */
    private $message;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="messageDocument")
     */
    private $sender;

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

    public function getFileName(): ?string
    {
        return $this->fileName;
    }

    public function setFileName(string $fileName): self
    {
        $this->fileName = $fileName;

        return $this;
    }

    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updatedAt;
    }

    public function setUpdatedAt(\DateTimeInterface $updatedAt): self
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    public function getType(): ?string
    {
        return $this->type;
    }

    public function setType(?string $type): self
    {
        $this->type = $type;

        return $this;
    }

    public function getMessage(): ?Message
    {
        return $this->message;
    }

    public function setMessage(?Message $message): self
    {
        $this->message = $message;

        return $this;
    }

    public function getSender(): ?User
    {
        return $this->sender;
    }

    public function setSender(?User $sender): self
    {
        $this->sender = $sender;

        return $this;
    }
}

js 用于从 twig 调用控制器

function getMessages(conversationId , userId) {
    superConversationId = conversationId;
    userIdEnCours       = userId;
    //* On vide ce qu'il y avait avant
    removeAllChildNodes(document.querySelector('.msg_history'));

    //* On remet toutes les conversations en blanc
    let allDivs = document.getElementsByClassName('chat_list');
    for (let div of allDivs) {
        div.style.background = '#f8f8f8';
    }

    //* background-color light-grey quand conversation selectionné
    $("#"+ conversationId).css('background', "#e1e1e1")

    let xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange = function () {
        //si requête validé on traite la réponse
        if (this.readyState == 4 && this.status == 200) {

            let messages   = JSON.parse(this.response);
            let discussion = document.querySelector('.msg_history');

            for (let message of messages) {
                let dateMessage = new Date(message.createdAt)
                var lastMessageId = message.id;

                //* Affichage selon envoyé ou reçu
                if (message.authorId == userIdEnCours) {
                    discussion.innerHTML += "<div class=\"outgoing_msg col-12 \"\><div class=\"sent_msg col-6 m-0\">"
                        + "<p class='m-0'>" + message.content + "</p>"
                        + "<span class=\"time_date\"> De " + message.author + " | " + dateMessage.toLocaleString() + "</span>"
                        + "</div>"
                    ;
                } else {
                    discussion.innerHTML += "<div class=\"incoming_msg col-12 \">"
                        + "<div class=\"received_msg col-12\"\><div class=\"received_withd_msg col-6\">"
                        + "<p>" + message.content + "</p>"
                        + "<span class=\"time_date_receiver\"> De " + message.author + " | " + dateMessage.toLocaleString() + "</span>"
                        + "</div></div>"
                        
                    ;
                }
            }

            //* scroll dernier message
            let divMessagerie       = document.querySelector(".msg_history");
            divMessagerie.scrollTop = divMessagerie.scrollHeight;
//vl le 13/09
// ne voyant pas l'utilité ...

/*             Interval = setInterval( () => {
                $.ajax({
                    type: "POST",
                    url : "/checkMessage/" + lastMessageId,
                    success: function (response) {
                        if (response === true) {
                            clearInterval(Interval);
                            getMessages(
                                superConversationId, 
                                userIdEnCours
                            );
                        }
                    },
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        alert(errorThrown);
                    }
                });
            }, 5000); */
        }
    };

    //! Ouverture de la requete (MOCK VERS PROD)
    //* PROD 
    // xmlhttp.open("GET", "http://www.generation-boomerang.com/messagerie/conv/" + conversationId);
    //* DEV
    xmlhttp.open("GET", "/messagerie/conv/" + conversationId);

    xmlhttp.send();
}

从对话中获取消息的控制器

/**
 * @Route("/messagerie/conv/{id}" , name="messagerie_getMessagesOfConv")
 * @Security("is_granted('ROLE_ABONNE') or is_granted('ROLE_ADMIN')", message="Merci de vous abonner au portail pour bénéficier de cette super fonctionnalité !")
 */
public function getMessagesOfConv(int $id, EntityManagerInterface $entityManager, ConversationRepository $conversationRepository, ParticipantRepository $participantRepository,MessageDocumentRepository $messageRepository) {
    //* Récup du user + check à faire
    $userEncours = $this->getUser();
    $userId = $userEncours->getId();
            //* Ckeck si la conversation appartient bien au user
    $check = $participantRepository->checkBelongs($id, $userId);
    if ($check != 1) {
        return $this->json('cette conv ne te regarde pas !');
    }

    $conversation = $conversationRepository->find($id);
    $messages = $conversation->getMessages();

 //   $documentsMessages = new ArrayCollection();//vl
    $allMessages = new ArrayCollection();
   // $docs=;
    foreach ($messages as $messageUnique) {
        $messId = $messageUnique->getId();
        $documentsMessages = $messageRepository->findDocByMessageId($messId);
 
        if($documentsMessages !== null){
            foreach($documentsMessages as $document){
              //  $docs=$document;
              $messageUnique->addMessageDocument($document);
            } 
            
        }

        $conversation->setLastMessage($messageUnique);
        
        $messageUnique = array(
            'id'        => $messageUnique->getId(),
            'author'    => $messageUnique->getUser()->getFullName(),
            'authorId'  => $messageUnique->getUser()->getId(),
            'content'   => $messageUnique->getContent(),
            'createdAt' => $messageUnique->getCreatedAt(),
            'messageDocuments'=>$messageUnique->getMessageDocument()
        );
        $allMessages->add($messageUnique);

    }
    

    $entityManager->persist($conversation);
    $entityManager->flush();
    //echo '<pre>';  var_dump( $conversation);exit;echo '</pre>';//
    return $this->json($allMessages);
}

对话实体

<?php

namespace App\Entity;

use App\Repository\ConversationRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ConversationRepository::class)
 */
class Conversation {
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\OneToOne(targetEntity=Message::class, cascade={"persist", "remove"})
     */
    private $lastMessage;

    /**
     * @ORM\OneToMany(targetEntity=Message::class, mappedBy="conversation")
     */
    private $messages;

    /**
     * @ORM\OneToMany(targetEntity="Participant", mappedBy="conversation")
     */
    private $participants;

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

    /**
     * @ORM\Column(type="datetime")
     */
    private $createdAt;

    public function __construct() {
        $this->participants = new ArrayCollection();
        $this->messages     = new ArrayCollection();
        $this->createdAt    = new \DateTime('now');
    }

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

    public function getLastMessage():?Message {
        return $this->lastMessage;
    }
    public function setLastMessage(?Message $lastMessage):self {
        $this->lastMessage = $lastMessage;
        return $this;
    }

    /**
     * @return Collection|Message[]
     */
    public function getMessages():Collection {
        return $this->messages;
    }
    public function addMessage(Message $message):self {
        if (!$this->messages->contains($message)) {
            $this->messages[] = $message;
            $message->setConversation($this);
        }
        return $this;
    }
    public function removeMessage(Message $message):self {
        if ($this->messages->contains($message)) {
            $this->messages->removeElement($message);
            // set the owning side to null (unless already changed)
            if ($message->getConversation() === $this) {
                $message->setConversation(null);
            }
        }
        return $this;
    }

     /**
     * @return Collection|Participant[]
     */
    public function getParticipants():Collection {
        return $this->participants;
    }

    public function addParticipant(Participant $participant):self {
        if (!$this->participants->contains($participant)) {
            $this->participants[] = $participant;
            $participant->setConversation($this);
        }
        return $this;
    }
    public function removeParticipant(Participant $participant):self {
        if ($this->participants->contains($participant)) {
            $this->participants->removeElement($participant);
            // set the owning side to null (unless already changed)
            if ($participant->getConversation() === $this) {
                $participant->setConversation(null);
            }
        }
        return $this;
    }

    /**
     * Get the value of title
     */ 
    public function getTitle() {
        return $this->title;
    }
    /**
     * Set the value of title
     * @return  self
     */ 
    public function setTitle($title) {
        $this->title = $title;
        return $this;
    }

    public function getCreatedAt():?\DateTimeInterface {
        return $this->createdAt;
    }
    public function setCreatedAt(\DateTimeInterface $createdAt):self {
        $this->createdAt = $createdAt;
        return $this;
    }
}

和参与者实体

<?php

namespace App\Entity;

use App\Repository\ParticipantRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ParticipantRepository::class)
 */
class Participant
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="participants")
     */
    private $user;

    /**
     * @ORM\ManyToOne(targetEntity="Conversation", inversedBy="participants")
     */
    private $conversation;

    private $messageReadAt;

    /**
     * Get the value of id
     */ 
    public function getId()
    {
        return $this->id;
    }

    /**
     * Get the value of user
     */ 
    public function getUser()
    {
        return $this->user;
    }

    /**
     * Set the value of user
     *
     * @return  self
     */ 
    public function setUser($user)
    {
        $this->user = $user;
        return $this;
    }

    /**
     * Get the value of conversation
     */ 
    public function getConversation()
    {
        return $this->conversation;
    }

    /**
     * Set the value of conversation
     *
     * @return  self
     */ 
    public function setConversation($conversation)
    {
        $this->conversation = $conversation;
        return $this;
    }

    /**
     * Get the value of messageReadAt
     */ 
    public function getMessageReadAt()
    {
        return $this->messageReadAt;
    }

    /**
     * Set the value of messageReadAt
     *
     * @return  self
     */ 
    public function setMessageReadAt($messageReadAt)
    {
        $this->messageReadAt = $messageReadAt;
        return $this;
    }
}

还有一个CreateMessageHandler和GetMessageHanler(但我不明白它是如何工作的)

CreateMessageHandler

namespace App\MessageHandler;
use App\Entity\User;
use App\Entity\Message;
use App\Entity\Conversation;
use App\Message\CreateMessage;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class CreateMessageHandler implements MessageHandlerInterface
{
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager) {
        $this->entityManager = $entityManager;
    }

    public function __invoke(CreateMessage $createMessage) 
    {
        $conversation = $this->entityManager->getRepository(Conversation::class)->find($createMessage->getConversationId());

        if(is_null($conversation))
        {
            $conversation = new Conversation();
            $this->entityManager->persist($conversation);
            $this->entityManager->flush();
        } else {
            $message = new Message(
                $createMessage->getContent(),
                $this->entityManager->getRepository(User::class)->find($createMessage->getUserId()),
                $conversation,
            );
           // if ()
        }

        // Debug
        // echo $createMessage->getContent();
        // echo $message->getUser()->getId();
        // echo $message->getConversation()->getId();

        $this->entityManager->persist($message);
        $this->entityManager->flush();
    }
}

GetMessageHandler

namespace App\MessageHandler;

use App\Entity\Message;
use App\Message\GetMessages;
use App\Repository\MessageRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class GetMessagesHandler implements MessageHandlerInterface
{
    private $entityManager;
    private $messageRepository;

    public function __construct(EntityManagerInterface $entityManager, MessageRepository $messageRepository) {
        $this->entityManager = $entityManager;
    }

    public function __invoke(GetMessages $message)
    {
        //Récupérer les messages de la conversation
        return $this->entityManager->getRepository(Message::class)->findBy(['conversation' => $message->getConversationId()]);
    }
}

我认为一切都在那里。 有点长抱歉... 希望有人能找到我有这个循环引用的原因

谢谢

我终于解决了问题:)
我在 MessageDocument 实体

的两个属性上使用了 @ignore 装饰器