使用 VichUploaderBundle 手动上传文件

Upload file manually with VichUploaderBundle

我正在尝试使用 VichUploaderBundle 手动上传文件

我的实体 BookingOrder 链接到一个用户,有一些其他字段和一个 vichUpload 字段。

预订订单实体:

<?php

namespace BookingBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use BookingBundle\Entity\Booking;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * BookingOrder
 *
 * @ORM\Table(name="booking_order")
 * @ORM\Entity(repositoryClass="BookingBundle\Repository\BookingOrderRepository")
 * @Vich\Uploadable
 */
class BookingOrder {

    public function __construct() {
        $this->bookings = new ArrayCollection();
        $this->drivingLicenceSize = 0;
        $this->confirmed = false;
        $this->creationDate = new \DateTime();
        $this->updatedAt = new \DateTime();
    }

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

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

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

    /**
     * 
     * @Vich\UploadableField(mapping="booking_drivinglicence", fileNameProperty="drivingLicence", size="drivingLicenceSize")
     * 
     * @var UploadedFile
     */
    private $drivingLicenceFile;

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

    /**
     * @ORM\Column(type="integer")
     *
     * @var integer
     */
    private $drivingLicenceSize;

    /**
     * @ORM\Column(type="datetime",nullable = true)
     *
     * @var \DateTime
     */
    private $drivingLicenceUpdatedAt;

    /**
     * @ORM\OneToMany(targetEntity="BookingBundle\Entity\Booking", mappedBy="bookingOrder")
     */
    private $bookings;

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

    /**
     * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="bookingOrders")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;

    /**
     * @var float
     *
     * @ORM\Column(name="totalCost", type="float")
     */
    private $totalCost;

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

    /**
     * Set creationDate
     *
     * @param \DateTime $creationDate
     *
     * @return BookingOrder
     */
    public function setCreationDate($creationDate) {
        $this->creationDate = $creationDate;

        return $this;
    }

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

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

        return $this;
    }

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

    function getUser() {
        return $this->user;
    }

    function setUser($user) {
        $this->user = $user;
    }

    function getDrivingLicenceUpdatedAt() {
        return $this->drivingLicenceUpdatedAt;
    }

    function setDrivingLicenceUpdatedAt(\DateTime $drivingLicenceUpdatedAt) {
        $this->drivingLicenceUpdatedAt = $drivingLicenceUpdatedAt;
    }

    /**
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
     * of 'UploadedFile' is injected into this setter to trigger the  update. If this
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
     * must be able to accept an instance of 'File' as the bundle will inject one here
     * during Doctrine hydration.
     *
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $drivingLicenceFile
     *
     * @return BookingOrder
     */
    public function setDrivingLicenceFile(UploadedFile $drivingLicenceFile = null) {
        $this->drivingLicenceFile = $drivingLicenceFile;
        if ($drivingLicenceFile) {
            $this->drivingLicenceUpdatedAt = new \DateTimeImmutable();
            $this->setDrivingLicenceSize($drivingLicenceFile->getSize());
        }
        return $this;
    }

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

    /**
     * @param string $drivingLicence
     *
     * @return BookingOrder
     */
    public function setDrivingLicence($drivingLicence) {
        $this->drivingLicence = $drivingLicence;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getDrivingLicence() {
        return $this->drivingLicence;
    }

    /**
     * @param integer $imageSize
     *
     * @return BookingOrder
     */
    public function setDrivingLicenceSize($drivingLicenceSize) {
        $this->drivingLicenceSize = $drivingLicenceSize;
        return $this;
    }

    /**
     * @return integer|null
     */
    public function getDrivingLicenceSize() {
        return $this->drivingLicenceSize;
    }

    public function addBooking(Booking $booking) {
        $booking->setBookingOrder($this);
        // si la resa fait déjà partie de la collection on ne l'ajoute pas
        if (!$this->bookings->contains($booking)) {
            $this->bookings->add($booking);
        }
    }

    public function removeBooking(Booking $booking) {
        // Si la resa  fait déjà parti de la collection on la retire
        if ($this->bookings->contains($booking)) {
            $this->bookings->remove($booking);
            $booking->setBookingOrder(NULL);
        }
    }

    public function getBookings() {
        return $this->bookings;
    }

    public function getConfirmed() {
        return $this->confirmed;
    }

    public function setConfirmed($confirmed) {
        $this->confirmed = $confirmed;
    }

    public function getTotalCost() {
        return $this->totalCost;
    }

    public function setTotalCost($totalCost) {
        $this->totalCost = $totalCost;
    }

}

控制器:

public function basketAction(Request $request) {
        //recuperation des repository necessaire
        $bookingOrderRepository = $this->getDoctrine()->getRepository('BookingBundle:BookingOrder');

        //recuperation du user courant
        $user = $this->getUser();
        //on recupere la liste des reservation non confirmee (dans le panier) du user courant
        $bookingOrder = $bookingOrderRepository->getBookingOrderByUserAndConfirmed($user, false);
        $bookingList = $bookingOrder->getBookings();

        //creation du formulaire de reservation
        $docForm = $this->createFormBuilder()
        ->add('firstName', TextType::class, array(
        'required' => 'true',
        'label' => false,
        'data' => $user->getFirstName()
        ))
        ->add('lastName', TextType::class, array(
        'required' => 'true',
        'label' => false,
        'data' => $user->getLastName()
        ))
        ->add('tel', TextType::class, array(
        'data' => $user->getTel()
        ))
        ->add('persoEmail', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\EmailType'), array(
        'data' => $user->getPersoEmail()
        ))
        ->add('booking_drivinglicence', VichFileType::class, array(
        'label' => false,
        'required' => true
        ))
        ->add('booking_residenceproof', VichFileType::class, array(
        'label' => false,
        'required' => true
        ))
        ->add('booking_idcard', VichFileType::class, array(
        'label' => false,
        'required' => true
        ))
        ->getForm();

        $docForm->handleRequest($request);

        if ($docForm->isSubmitted() && $docForm->isValid()) {
            $tel = $docForm["tel"]->getData();
            $drivingLicence = $docForm["booking_drivinglicence"]->getData();
            $residenceProof = $docForm["booking_residenceproof"]->getData();
            $idCard = $docForm["booking_idcard"]->getData();


            $fileThumbnail = new UploadedFile($drivingLicence(), $drivingLicence->getClientOriginalName(), $drivingLicence->getClientMimeType(), $drivingLicence->getClientSize(), null, true);




            $bookingOrder->setDrivingLicenceFile($fileThumbnail);

            $em = $this->getDoctrine()->getManager();
            $em->persist($bookingOrder);
            $em->flush();

            return $this->redirectToRoute('platform_homepage');
        }


        return $this->render('PlatformBundle:Default:basket.html.twig', array(
                    'bookingList' => $bookingList,
                    'docForm' => $docForm->createView()
                        )
        );

起初我尝试没有这一行:

$fileThumbnail = new UploadedFile(
    $drivingLicence(),
    $drivingLicence-getClientOriginalName(),
    $drivingLicence->getClientMimeType()
    $drivingLicence-getClientSize(), null, true
);

但仅限于此方法:

$bookingOrder->setDrivingLicenceFile($drivingLicence);

在这种情况下,我没有得到任何错误,但是即使在数据库中也没有上传文件,updatedDate 修改得很好。

正如我在其他主题上阅读的那样,我需要触发 Doctrine 上传,这就是为什么我要尝试创建一个新的 FileUpload 对象,其测试字段等于 true

我的错误是认为我需要指定一个 vichUploader 字段。

但我所要做的就是像这样创建一个 FormType:

namespace BookingBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use UserBundle\Form\UserBookingOrderType;
use Symfony\Component\Form\Extension\Core\Type\FileType;

class BookingOrderType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {

        $builder
                ->add('user', UserBookingOrderType::class)
                ->add('drivingLicenceFile', FileType::class, array(
                    "label" => false
                ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver) {
        $resolver->setDefaults(array(
            'cascade_validation' => true,
        ));
    }

    public function getBlockPrefix() {
        return 'cp_create_booking_order';
    }

}

在我的控制器中调用它:

 $docForm = $this->createForm(BookingOrderType::class, $bookingOrder);

        $docForm->handleRequest($request);

        if ($docForm->isSubmitted() && $docForm->isValid()) {

            $em = $this->getDoctrine()->getManager();
            $em->persist($bookingOrder);
            $em->flush();

            return $this->redirectToRoute('platform_homepage');
        }

而且,最重要的是,不要忘记清除缓存!!

现在,一切正常,上传也很完美