【问题标题】:Pre_submit problem saving data on Symfony3在 Symfony3 上保存数据的 Pre_submit 问题
【发布时间】:2019-02-14 17:53:55
【问题描述】:

我有一些公司,其中有一个徽标字段。我在编辑页面中的想法是,如果在编辑表单中,该字段为空,保留我们之前在数据库中的徽标,因为这是一个必填字段。

我的想法是获取之前要提交的表单的数据并检查该字段是否为空以从数据库中获取数据以使用它进行更新。我使用了eventListener,但是当数据提交时,它不会改变为null。我对这个 symfony 版本几乎是新手,但我无法做到这一点。你可以帮帮我吗。谢谢,

/**
    * @Route("/admin/companies/edit/{id}", name="edit_company")
    * Method({"GET", "POST"})
    */
    public function editCompany(Request $request, $id){

        $company = new Company();
        $company = $this->getDoctrine()->getRepository(Company::class)->find($id);      

        $form = $this->createFormBuilder($company)
            ->add('name', TextType::class, array('attr' => array('class' => 'form-control')))
            ->add('description', TextAreaType::class, array('attr' => array('class' => 'form-control summernote')))
            ->add('telephone', TextType::class, array('attr' => array('class' => 'form-control')))
            ->add('city', TextType::class, array('attr' => array('class' => 'form-control')))
            ->add('web', UrlType::class, array('attr' => array('class' => 'form-control')))
            ->add('image', FileType::class, array('data_class' => null, 'label' => false, 'required' => false, 'attr' => array('class' => 'form-control d-none')))            
            ->add('save', SubmitType::class, ['label' => 'Edit Company', 'attr' => array('class' => 'btn btn-success p-2 mt-5')])`enter code here`
            ->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
                $data = $event->getData();
                $form = $event->getForm();
                $image = $data['image'];
                if ($image == null){
                    $company_tmp = $this->getDoctrine()->getRepository(Company::class)->find($form->getData()->getId());
                    $data['image'] = $company_tmp->getImage();           
                    $event->setData($data);
                }               

            })          
            ->getForm();

        $form->handleRequest($request);


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

            $company = $form->getData();

            $file = $form->get('image')->getData();

            if ($file !== null){
                $fileName = 'company-'.$this->generateUniqueFileName().'.'.$file->guessExtension();                         
                // Move the file to the directory where brochures are stored
                try {
                    $moved = $file->move( $this->get('kernel')->getProjectDir() . '/public/uploads', $fileName );
                } catch (FileException $e) {
                   throw new HttpNotFoundException("Page not found");
                }
                $company->setImage($fileName);
            }

            $entityManager= $this->getDoctrine()->getManager();     
            $entityManager->flush();
            $flashbag = $this->get('session')->getFlashBag();           
            $flashbag->add("success", "Company Edited Correctly");  

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

        return $this->render('admin/edit_company.html.twig', 
            array(
                'form' => $form->createView(),
                'company' => $company,
            )
        );
    }

例如,如果之前要保存的图片名称是company122121.jpg,而编辑表单数据为空,则将company122121.jpg保存在数据库中。但结果始终为空。我已经检查了侦听器上的 $event->getData() 并且数据是正确的,但是当我在 isSubmitted() 之后获取数据时,数据为空。

Result with dump listener and image after submit

【问题讨论】:

    标签: php symfony symfony-3.4


    【解决方案1】:

    来自官方文档: https://symfony.com/doc/current/controller/upload_file.html

    创建表单以编辑已持久化的项目时,文件表单 type 仍然需要一个 File 实例。作为现在的持久实体 仅包含相对文件路径,您首先必须连接 使用存储的文件名配置的上传路径并创建一个新的 文件类:

    use Symfony\Component\HttpFoundation\File\File;
    // ...
    
    $product->setBrochure(
        new File($this->getParameter('brochures_directory').'/'.$product->getBrochure())
    );
    

    所以我认为你应该添加

    $company->setImage(new File($pathToYourImage));
    

    之后

    $company = $this->getDoctrine()->getRepository(Company::class)->find($id);      
    

    【讨论】:

    • 完美@Alex83690。它工作完美。我添加了代码,它在侦听器中完美运行: if ($image == null){ $company_tmp = $this->getDoctrine()->getRepository(Company::class)->find($form->getData( )->getId()); $file = new File('uploads/' . $company_tmp->getImage()); $data['image'] = $file; $event->setData($data);我将按照您的建议探索将图像作为图像而不是文件上传的选项。我是这个版本的新手,我还在学习。
    【解决方案2】:

    我还建议通过 Doctrine Event Subscriber 包含的服务处理图像上传。

    我还将图像作为媒体对象保存到数据库中,其中包含已通过 postLoad 侦听器正确解析的上传图像的文件名。

    参考: Doctrine Event Subscriber File Upload Service

    class UploadHandler
    {
        /** @var string */
        private $fileDirectory;
    
        /**
         * FileUploader constructor.
         *
         * @param string $fileDirectory
         */
        public function __construct(
            string $fileDirectory
        ) {
            $this->fileDirectory = $fileDirectory;
        }
    
        /**
         * Move the file to the upload directory.
         *
         * @param UploadedFile $file
         *
         * @return string
         */
        public function upload(UploadedFile $file) {
            $fileName = md5(uniqid() . '.' . $file->guessExtension());
    
            $file->move($this->getFileDirectory(), $fileName);
    
            return $fileName;
        }
    
        /**
         * @return string
         */
        public function getFileDirectory(): string {
            return $this->fileDirectory;
        }
    }
    
    class UploadEventSubscriber
    {
        /**
         * @var FileUploader
         */
        private $uploader;
    
        /**
         * UploadEventSubscriber constructor.
         * @param FileUploader $uploader
         */
        public function __construct(
            FileUploader $uploader
        )
        {
            $this->uploader = $uploader;
        }
    
        /**
         * Returns an array of events this subscriber wants to listen to.
         *
         * @return string[]
         */
        public function getSubscribedEvents()
        {
            return [
                'prePersist',
                'preUpdate',
                'postLoad'
            ];
        }
    
        /**
         * Pre-Persist method for Media.
         *
         * @param LifecycleEventArgs $args
         */
        public function prePersist(LifecycleEventArgs $args) {
            /** @var Media $entity */
            $entity = $args->getEntity();
    
            if (!$this->validInstance($entity)) {
                return;
            }
    
            $this->uploadFile($entity);
        }
    
        /**
         * Pre-Update method for Media.
         *
         * @param LifecycleEventArgs $args
         */
        public function preUpdate(LifecycleEventArgs $args) {
            /** @var Media $entity */
            $entity = $args->getEntity();
    
            if (!$this->validInstance($entity)) {
                return;
            }
    
            $this->uploadFile($entity);
        }
    
        /**
         * Post-Load method for Media
         *
         * @param LifecycleEventArgs $args
         */
        public function postLoad(LifecycleEventArgs $args) {
            /** @var Media $entity */
            $entity = $args->getEntity();
    
            if (!$this->validInstance($entity)) {
                return;
            }
    
            $fileName = $entity->getImage();
            if($fileName) {
                $entity->setImage(new File($this->uploader->getFileDirectory() . '/' . $fileName));
            }
        }
    
        /**
         * Check if a valid entity is given.
         *
         * @param object $entity
         * @return bool
         */
        private function validInstance($entity)
        {
            return $entity instanceof Media;
        }
    
        /**
         * Upload the file
         * @param Media $entity
         */
        private function uploadFile(Media $entity)
        {
            $file = $entity->getImage();
    
            if($file instanceof UploadedFile) {
                $fileName = $this->uploader->upload($file);
                $entity->setImage($fileName);
            }
        }
    }
    
    

    【讨论】:

      猜你喜欢
      • 2011-08-01
      • 2018-06-16
      • 1970-01-01
      • 2011-09-03
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 1970-01-01
      相关资源
      最近更新 更多