Symfony 3:文件类型多和多对多数据库关系
Symfony 3: FileType multiple and Many-to-Many database relation
我得到了名为 SupportMessage 的实体,其中包含来自我的支持(票证)系统的消息。我想实现允许用户和支持代理将文件附加到他们的帖子的功能。
我还有一个名为 Files 的实体,其中列出了我项目中的所有文件:文件 ID、文件名、用户和上传日期。
当用户在我的支持系统中写消息时,他可以附加多个文件。我认为使用 multiple=true
比创建 CollectionType 的 FileType 按钮更优雅,但我真的不知道如何实现此功能并使其工作。在官方文档和 Google 中未找到有关此案例的任何信息。
当我发送表单时,我得到了一个 UploadedFile 对象数组,但没有 ArrayCollection,所以一切都失败了:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\SupportMessage#$attachments", got "Symfony\Component\HttpFoundation\File\UploadedFile" instead.
控制器:
/**
* @Security("is_granted('ALLOWED_TO_VIEW_SUPPORT_TICKET', supportTicket)")
* @Route("/support/ticket-{supportTicket}", name="view_ticket")
*
* @param Request $request
* @param SupportTicket $supportTicket
* @return Response
*/
public function viewTicket(Request $request, SupportTicket $supportTicket)
{
$translator = $this->get('translator');
$breadcrumbs = $this->get('white_october_breadcrumbs');
$breadcrumbs->addRouteItem('app.name', 'homepage');
$breadcrumbs->addRouteItem('page_title.support', 'my_support_tickets');
$breadcrumbs->addItem($supportTicket->getTitle());
$supportMessage = new SupportMessage();
$supportMessage->setSupportTicket($supportTicket);
$supportMessage->setUser($this->getUser());
$form = $this->createForm(SupportMessageType::class, $supportMessage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($supportMessage->getAttachments() as $attachment) {
$fileName = $this->get('app.file_uploader')->upload($attachment);
$file = new File();
$file->setFilename($fileName);
$file->setUser($this->getUser());
//$supportMessage->addAttachment($file);
}
//dump($supportMessage);die;
$em = $this->getDoctrine()->getManager();
$em->persist($supportMessage);
$em->flush();
$this->addFlash('notice', $translator->trans('support.flash_message.sent'));
return $this->redirect($request->getUri());
}
return $this->render('support/view-ticket.html.twig', [
'title' => $supportTicket->getTitle(),
'supportTicket' => $supportTicket,
'form' => $form->createView()
]);
}
服务:
namespace AppBundle\Service;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->targetDir, $fileName);
return $fileName;
}
}
SupportMessage 实体:
namespace AppBundle\Entity;
use Carbon\Carbon;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class SupportMessage
{
public function __construct()
{
$this->postedAt = new \DateTime();
$this->attachments = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="text")
*
* @Assert\NotBlank
* @Assert\Length(max=65535)
*
* @var string
*/
private $message;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $postedAt;
/**
* @return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string
*/
public function getMessage(): ?string
{
return $this->message;
}
/**
* @param string $message
*/
public function setMessage(?string $message)
{
$this->message = $message;
}
/**
* @return \DateTime
*/
public function getPostedAt()
{
return $this->postedAt;
}
/**
* @return string
*/
public function getPostedAgo()
{
Carbon::setLocale('ru');
return Carbon::instance($this->postedAt)->diffForHumans();
}
/**
* @param \DateTime $postedAt
*/
public function setPostedAt($postedAt)
{
$this->postedAt = $postedAt;
}
/**
* @ORM\ManyToOne(targetEntity="User")
* @ORM\JoinColumn(nullable=false)
*
* @var User
*/
private $user;
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
*/
public function setUser($user)
{
$this->user = $user;
}
/**
* @ORM\ManyToOne(targetEntity="SupportTicket", inversedBy="supportMessages")
*
* @var SupportTicket
*/
private $supportTicket;
/**
* @return SupportTicket
*/
public function getSupportTicket()
{
return $this->supportTicket;
}
/**
* @param SupportTicket $supportTicket
*/
public function setSupportTicket($supportTicket)
{
$this->supportTicket = $supportTicket;
}
/**
* @ORM\ManyToMany(targetEntity="File", inversedBy="supportMessages")
*
* @var File[]
*/
private $attachments;
/**
* @return File[]
*/
public function getAttachments()
{
return $this->attachments;
}
/**
* @param File[] $attachments
*/
public function setAttachments($attachments)
{
foreach ($attachments as $attachment) {
$this->attachments->add($attachment);
}
//dump($this->attachments);die;
}
/**
* @param File $attachment
*/
public function addAttachment($attachment)
{
$this->attachments->add($attachment);
}
}
文件实体:
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class File
{
public function __construct()
{
$this->uploadedAt = new \DateTime();
$this->supportMessages = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="string")
*
* @Assert\File
*
* @var string
*/
private $filename;
/**
* @ORM\Column(type="string")
*
* @var User
*/
private $user;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $uploadedAt;
/**
* @return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string
*/
public function getFilename(): ?string
{
return $this->filename;
}
/**
* @param string $filename
*/
public function setFilename(?string $filename)
{
$this->filename = $filename;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param mixed $user
*/
public function setUser($user)
{
$this->user = $user;
}
/**
* @return \DateTime
*/
public function getUploadedAt()
{
return $this->uploadedAt;
}
/**
* @param \DateTime $uploadedAt
*/
public function setUploadedAt($uploadedAt)
{
$this->uploadedAt = $uploadedAt;
}
/**
* @ORM\ManyToMany(targetEntity="SupportMessage", mappedBy="attachments")
*
* @var Collection|SupportMessage[]
*/
private $supportMessages;
/**
* @return Collection|SupportMessage[]
*/
public function getSupportMessages()
{
return $this->supportMessages;
}
/**
* @param Collection|SupportMessage[] $supportMessages
*/
public function setSupportMessages($supportMessages)
{
$this->supportMessages = $supportMessages;
}
/**
* @param SupportMessage $supportMessage
*/
public function addSupportMessage($supportMessage)
{
$supportMessage->addAttachment($this);
$this->supportMessages->add($supportMessage);
}
}
非常感谢您的提前帮助。
同事终于找到问题了。它在我的控制器中。我在那里附加了 UploadedFile
个对象,但事实上我需要附加我的实体 File
个对象。
固定代码被截断:
if ($form->isSubmitted() && $form->isValid()) {
$attachments = new ArrayCollection();
foreach ($supportMessage->getAttachments() as $attachment) {
$fileName = $this->get('app.file_uploader')->upload($attachment);
$file = new File();
$file->setFilename($fileName);
$file->setUser($this->getUser());
$attachments->add($file);
//$supportMessage->addAttachment($file);
}
$supportMessage->setAttachments($attachments);
// ... other code here ...
}
我得到了名为 SupportMessage 的实体,其中包含来自我的支持(票证)系统的消息。我想实现允许用户和支持代理将文件附加到他们的帖子的功能。
我还有一个名为 Files 的实体,其中列出了我项目中的所有文件:文件 ID、文件名、用户和上传日期。
当用户在我的支持系统中写消息时,他可以附加多个文件。我认为使用 multiple=true
比创建 CollectionType 的 FileType 按钮更优雅,但我真的不知道如何实现此功能并使其工作。在官方文档和 Google 中未找到有关此案例的任何信息。
当我发送表单时,我得到了一个 UploadedFile 对象数组,但没有 ArrayCollection,所以一切都失败了:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\SupportMessage#$attachments", got "Symfony\Component\HttpFoundation\File\UploadedFile" instead.
控制器:
/**
* @Security("is_granted('ALLOWED_TO_VIEW_SUPPORT_TICKET', supportTicket)")
* @Route("/support/ticket-{supportTicket}", name="view_ticket")
*
* @param Request $request
* @param SupportTicket $supportTicket
* @return Response
*/
public function viewTicket(Request $request, SupportTicket $supportTicket)
{
$translator = $this->get('translator');
$breadcrumbs = $this->get('white_october_breadcrumbs');
$breadcrumbs->addRouteItem('app.name', 'homepage');
$breadcrumbs->addRouteItem('page_title.support', 'my_support_tickets');
$breadcrumbs->addItem($supportTicket->getTitle());
$supportMessage = new SupportMessage();
$supportMessage->setSupportTicket($supportTicket);
$supportMessage->setUser($this->getUser());
$form = $this->createForm(SupportMessageType::class, $supportMessage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
foreach ($supportMessage->getAttachments() as $attachment) {
$fileName = $this->get('app.file_uploader')->upload($attachment);
$file = new File();
$file->setFilename($fileName);
$file->setUser($this->getUser());
//$supportMessage->addAttachment($file);
}
//dump($supportMessage);die;
$em = $this->getDoctrine()->getManager();
$em->persist($supportMessage);
$em->flush();
$this->addFlash('notice', $translator->trans('support.flash_message.sent'));
return $this->redirect($request->getUri());
}
return $this->render('support/view-ticket.html.twig', [
'title' => $supportTicket->getTitle(),
'supportTicket' => $supportTicket,
'form' => $form->createView()
]);
}
服务:
namespace AppBundle\Service;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileUploader
{
private $targetDir;
public function __construct($targetDir)
{
$this->targetDir = $targetDir;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->targetDir, $fileName);
return $fileName;
}
}
SupportMessage 实体:
namespace AppBundle\Entity;
use Carbon\Carbon;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class SupportMessage
{
public function __construct()
{
$this->postedAt = new \DateTime();
$this->attachments = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="text")
*
* @Assert\NotBlank
* @Assert\Length(max=65535)
*
* @var string
*/
private $message;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $postedAt;
/**
* @return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string
*/
public function getMessage(): ?string
{
return $this->message;
}
/**
* @param string $message
*/
public function setMessage(?string $message)
{
$this->message = $message;
}
/**
* @return \DateTime
*/
public function getPostedAt()
{
return $this->postedAt;
}
/**
* @return string
*/
public function getPostedAgo()
{
Carbon::setLocale('ru');
return Carbon::instance($this->postedAt)->diffForHumans();
}
/**
* @param \DateTime $postedAt
*/
public function setPostedAt($postedAt)
{
$this->postedAt = $postedAt;
}
/**
* @ORM\ManyToOne(targetEntity="User")
* @ORM\JoinColumn(nullable=false)
*
* @var User
*/
private $user;
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
*/
public function setUser($user)
{
$this->user = $user;
}
/**
* @ORM\ManyToOne(targetEntity="SupportTicket", inversedBy="supportMessages")
*
* @var SupportTicket
*/
private $supportTicket;
/**
* @return SupportTicket
*/
public function getSupportTicket()
{
return $this->supportTicket;
}
/**
* @param SupportTicket $supportTicket
*/
public function setSupportTicket($supportTicket)
{
$this->supportTicket = $supportTicket;
}
/**
* @ORM\ManyToMany(targetEntity="File", inversedBy="supportMessages")
*
* @var File[]
*/
private $attachments;
/**
* @return File[]
*/
public function getAttachments()
{
return $this->attachments;
}
/**
* @param File[] $attachments
*/
public function setAttachments($attachments)
{
foreach ($attachments as $attachment) {
$this->attachments->add($attachment);
}
//dump($this->attachments);die;
}
/**
* @param File $attachment
*/
public function addAttachment($attachment)
{
$this->attachments->add($attachment);
}
}
文件实体:
namespace AppBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class File
{
public function __construct()
{
$this->uploadedAt = new \DateTime();
$this->supportMessages = new ArrayCollection();
}
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*
* @var int
*/
private $id;
/**
* @ORM\Column(type="string")
*
* @Assert\File
*
* @var string
*/
private $filename;
/**
* @ORM\Column(type="string")
*
* @var User
*/
private $user;
/**
* @ORM\Column(type="datetime")
*
* @var \DateTime
*/
private $uploadedAt;
/**
* @return int
*/
public function getId(): ?int
{
return $this->id;
}
/**
* @return string
*/
public function getFilename(): ?string
{
return $this->filename;
}
/**
* @param string $filename
*/
public function setFilename(?string $filename)
{
$this->filename = $filename;
}
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param mixed $user
*/
public function setUser($user)
{
$this->user = $user;
}
/**
* @return \DateTime
*/
public function getUploadedAt()
{
return $this->uploadedAt;
}
/**
* @param \DateTime $uploadedAt
*/
public function setUploadedAt($uploadedAt)
{
$this->uploadedAt = $uploadedAt;
}
/**
* @ORM\ManyToMany(targetEntity="SupportMessage", mappedBy="attachments")
*
* @var Collection|SupportMessage[]
*/
private $supportMessages;
/**
* @return Collection|SupportMessage[]
*/
public function getSupportMessages()
{
return $this->supportMessages;
}
/**
* @param Collection|SupportMessage[] $supportMessages
*/
public function setSupportMessages($supportMessages)
{
$this->supportMessages = $supportMessages;
}
/**
* @param SupportMessage $supportMessage
*/
public function addSupportMessage($supportMessage)
{
$supportMessage->addAttachment($this);
$this->supportMessages->add($supportMessage);
}
}
非常感谢您的提前帮助。
同事终于找到问题了。它在我的控制器中。我在那里附加了 UploadedFile
个对象,但事实上我需要附加我的实体 File
个对象。
固定代码被截断:
if ($form->isSubmitted() && $form->isValid()) {
$attachments = new ArrayCollection();
foreach ($supportMessage->getAttachments() as $attachment) {
$fileName = $this->get('app.file_uploader')->upload($attachment);
$file = new File();
$file->setFilename($fileName);
$file->setUser($this->getUser());
$attachments->add($file);
//$supportMessage->addAttachment($file);
}
$supportMessage->setAttachments($attachments);
// ... other code here ...
}