Pre_submit проблема сохранения данных на Symfony3 - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть несколько компаний, где есть поле для логотипа.Моя идея на странице редактирования заключается в том, что если в форме редактирования поле будет пустым, сохранится логотип, который у нас был ранее в БД, потому что это обязательное поле.

Моя идея состояла в том, чтобы получить данные формы, которые должны быть отправлены ранее, и проверить, является ли поле пустым, чтобы получить данные из базы данных для их обновления.Я использовал 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 (), данные равны нулю.

Результат с прослушивателем дампа и изображением после отправки

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Я бы также предложил обработать загрузку изображений через Службу, которая включена через подписчика событий Doctrine.

Я также сохраняю изображения как объекты мультимедиа в базе данных, которая содержит имя файла загруженных изображений, котороеразрешается корректно через слушателя postLoad.

Ссылка: Подписчик события Doctrine Служба загрузки файлов

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);
        }
    }
}

0 голосов
/ 14 февраля 2019

Из официальной документации: https://symfony.com/doc/current/controller/upload_file.html

При создании формы для редактирования уже сохраненного элемента тип формы файла все еще ожидает экземпляр файла.Поскольку постоянная сущность теперь содержит только относительный путь к файлу, сначала необходимо объединить сконфигурированный путь загрузки с сохраненным именем файла и создать новый класс файлов:

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);      
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...