私のサポート(チケット)システムからのメッセージを含むSupportMessageというエンティティがあります。私はユーザーとサポートエージェントが自分の投稿にファイルを添付できるようにする機能を実装したいと思います。Symfony 3:FileType multipleと多対多データベースの関係
ファイルファイルID、ファイル名、ユーザー、アップロード日など、プロジェクトのすべてのファイルがリストされています。
ユーザーがサポートシステムにメッセージを書き込むと、複数のファイルを添付できます。私はmultiple=true
をFileTypeボタンのCollectionTypeを作成するよりもエレガントな方法だと思いますが、この機能を実装して動作させる方法はわかりません。このケースについて公式のドキュメントとGoogleで情報を見つけられませんでした。
私がフォームを送信すると、私はにUploadedFileオブジェクトの配列ではなく、あるArrayCollectionを得たので、すべてが失敗します。
タイプの期待値を「教義\共通\コレクション\コレクション|配列」の関連フィールドの"AppBundle \ Entity \ SupportMessage#$ attachments"には、代わりに "Symfony \ Component \ HttpFoundation \ File \ UploadedFile"があります。
コントローラー:
/**
* @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);
}
}
事前に助けてくれてありがとうございました。
エンティティ、およびフォームクラスの両方を投稿してください。 –
@michail_w、私は私の質問を更新しました。 – terron