VichUploaderBundle未保存文件名称字段为NULL

时间:2015-02-15 02:25:58

标签: symfony vichuploaderbundle

我有一个应用程序,允许用户在申请课程时上传简历。返回并显示输入表单而没有错误。提交表单时不会抛出任何错误。上传的文件位于POST数据中 - 作为UploadedFile和cvUpdatedAt字段的实例设置。但是,当记录保存到数据库时,用于存储文件名的列将设置为NULL。

这是我的实体:

<?php

namespace My\CamsBundle\Entity;

use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity(repositoryClass="My\CamsBundle\Entity\Repository\ApplicationRepository")
 * @ORM\Table(name="application")
 * @Vich\Uploadable
 * @ORM\HasLifecycleCallbacks()
 */
class Application {

  /**
   * @ORM\Id
   * @ORM\Column(type="integer")
   * @ORM\GeneratedValue(strategy="AUTO")
   */
  protected $id;

  /**
   * @Assert\File(
   *     maxSize="2M",
   * )
   * @Vich\UploadableField(mapping="cv_file", fileNameProperty="cvName")
   *
   * This is not a mapped field of entity metadata, just a simple property.
   *
   * @var File $cvFile
   */
  protected $cvFile;

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

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


  public function __construct() {  }

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

  /**
   * 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 $cv
   */
  public function setCvFile(File $cv = null) {
    $this->cvFile = $cv;

    if ($cv) {
      // It is required that at least one field changes if you are using doctrine
      // otherwise the event listeners won't be called and the file is lost
      $this->cvUpdatedAt = new \DateTime('now');
    }
  }

  /**
   * @return File
   */
  public function getCvFile() {
    return $this->cvFile;
  }

  /**
   * @param string $cvName
   */
  public function setCvName($cvName) {
    $this->cvName = $cvName;
  }

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

  /**
   * Set cvUpdatedAt
   *
   * @param \DateTime $cvUpdatedAt
   * @return Application
   */
  public function setCvUpdatedAt($cvUpdatedAt) {
    $this->cvUpdatedAt = $updatcvUpdatedAt;

    return $this;
  }

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

}

以下是表格:

<?php

namespace My\CamsBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ApplicationType extends AbstractType {

  public function buildForm(FormBuilderInterface $builder, array $options) {
    if (array_key_exists('action', $options)) {
      $builder->setAction($options['action']);
    }

    // See http://lrotherfield.com/blog/symfony2-forms-hidden-entity-type-part-2/
    $builder->add('cvFile', 'vich_file', array(
        'required'      => false,
        'allow_delete'  => true, // not mandatory, default is true
        'download_link' => true, // not mandatory, default is true
        'label'         => 'Upload CV',
      ));

    $builder->add('save', 'submit', array(
      'label' => 'Save',
      'attr' => array(
        'class' => 'btn btn-action'
      )
    ));

    // Basic query builder solution. Not much better than the documentation.
    // http://inchoo.net/dev-talk/symfony2-entity-field-type/
  }

  public function getName() {
    return 'application';
  }

  public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults(array(
      'data_class' => 'My\CamsBundle\Entity\Application',
    ));
  }

}

这是配置:

imports:
    - { resource: parameters.yml }
    - { resource: security.yml }
    - { resource: @MyCamsBundle/Resources/config/config.yml }

framework:
    #esi:             ~
    #translator:      { fallback: "%locale%" }
    secret:          "%secret%"
    router:
        resource: "%kernel.root_dir%/config/routing.yml"
        strict_requirements: ~
    form:            ~
    csrf_protection: ~
    validation:      { enable_annotations: true }
    templating:
        engines: ['twig']
        #assets_version: SomeVersionScheme
    default_locale:  "%locale%"
    trusted_proxies: ~
    session:         ~
    fragments:       ~
    http_method_override: true

# Twig Configuration
twig:
    debug:            "%kernel.debug%"
    strict_variables: "%kernel.debug%"
    form:
        resources:
            - 'VichUploaderBundle:Form:fields.html.twig'


# Doctrine Configuration
doctrine:
    dbal:
        default_connection: default
        connections:
            default:
                driver:   "%database_driver%"
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                charset:  UTF8
            customer:
                driver:   "%database_driver2%"
                host:     "%database_host2%"
                port:     "%database_port2%"
                dbname:   "%database_name2%"
                user:     "%database_user2%"
                password: "%database_password2%"
                charset:  UTF8

    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        entity_managers:
            default:
                auto_mapping: true
                mappings:
                  MyCamsBundle: ~


vich_uploader:
    db_driver: orm

    mappings:
        cv_file:
            uri_prefix:         /uploads/documents
            upload_destination: %kernel.root_dir%/../web/uploads/documents
            #namer:              vich_uploader.namer_uniqid

            inject_on_load:     false
            delete_on_update:   true
            delete_on_remove:   true

表单模板:

{% extends 'MyCamsBundle::layout.html.twig' %}
{% form_theme form 'MyCamsBundle:Form:fields.html.twig' %}

{% block body %}
<div class="main">
    {{ form_errors(form) }}
    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
            <div class="heading">Application</div>
        </div>
    </div>


    <section id="application-form">
        {{ form_start(form) }}
    <div class="row well demonstrator-experience">
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 cv-details">

        <span class="btn btn-action btn-file">
            {{ form_label(form.cvFile) }} {{ form_widget(form.cvFile) }}
        </span>

        </div>

    <div class="row">
        <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 text-right">
        </div>
        {{ form_widget(form.save) }}
    </div>
    {{ form_end(form) }}
    </section>

</div>
{% endblock %}

控制器:

<?php

namespace My\CamsBundle\Controller;

use DateTime;
use Doctrine\ORM\EntityManager;
use Exception;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use My\CamsBundle\Entity\Application;
use My\CamsBundle\Form\ApplicationType;

/**
 * Apply for a casual position.
 *
 * Class ApplicationController
 * @package My\CamsBundle\Controller
 */
class ApplicationController extends Controller
{

    /**
     * Application form.
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     *
     * @Route("/application/create")
     */
    public function createAction()
    {
        $application = new Application();
        $em = $this->getDoctrine()->getManager();
        $form = $this->createFormModel($application);

        return $this->render('MyCamsBundle:Application:create.html.twig', array(
            'form' => $form->createView(),
        ));
    }

    /**
     * Application save form.
     *
     * @param \Symfony\Component\HttpFoundation\Request $request
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     *
     * @Route("/application/save")
     */
    public function saveAction(Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $raw_application = $request->get('application');
        $request->request->set('application', $raw_application);
        $application = new Application();
        $form = $this->createFormModel($application);
        $form->handleRequest($request);
        $application_id = 0;

        try {
            if ($form->isValid()) {
                $application = $form->getData();

                $em->merge($application);
                $em->flush();
                $application_id = $application->getId();
            } else {
                return $this->render('MyCamsBundle:Application:create.html.twig', array(
                    'form' => $form->createView(),
                ));
            }
        } catch (Exception $e) {
            $request->getSession()->getFlashBag()->add(
                'notice', 'Failed to save changes'
            );
            $logger = $this->get('logger');
            $logger->error($e->getMessage());

            return $this->render('MyCamsBundle:Application:create.html.twig', array(
                'form' => $form->createView(),
            ));
        }

        return $this->redirect($this->generateUrl('my_cams_application_update'));
    }

    /**
     * Application edit form. This is the applicant's dashboard.
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     *
     * @Route("/application/update")
     */
    public function updateAction()
    {
        $em = $this->getDoctrine()->getManager();

        // etc.
    }

    /**
     * @param $application
     * @return \Symfony\Component\Form\Form
     */
    private function createFormModel($application)
    {
        $form = $this->createForm(new ApplicationType(), $application, array(
                'action' => $this->generateUrl('my_cams_application_save')
            )
        );

        return $form;
    }

}

和存储库:

<?php

namespace My\CamsBundle\Entity\Repository;

use Doctrine\ORM\EntityRepository;

/**
 * ApplicationRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class ApplicationRepository extends EntityRepository
{
}

我不确定vich_uploader的映射是否正确加载。我无法在实体和表单定义中看到任何遗漏。

1 个答案:

答案 0 :(得分:0)

不确定是否有帮助,但可以更改:$cvUpdatedAt$updatedAt。就我而言,它奏效了。