filesymfonyfile-uploaddoctrine-ormedit

Symfony2 simple file upload edit without entity


Please help me out here because I can't believe my eyes.

I refuse to use some 3rd party plugin for file uploads, and refuse to create a separate entity for a file/document. I just want simple file upload that I would do in Zend/Laravel and so on.

I have a invoice table with the last column name "attachment", I want to store here its sanitized name (eg: 123421_filename.jpg ), the addition form and upload went well.

This here is my code:

//AddAction
     $file=$form['attachment']->getData();
        $fileName=$file->getClientOriginalName();
        $sanitizedFilename=rand(1, 99999).'_'.$fileName;
        $dir='files/'.$userId.'/';
        $file->move($dir, $sanitizedFilename);
    ...
        $invoice->setAttachment($sanitizedFilename);
        $em = $this->getDoctrine()->getManager();
        $em->persist($invoice);

First problem I have and don't know how to solve is using the edit form.. I have a formbuilder

   $builder->add('attachment', 'file',array('data_class'=>null))

Because I don't have a "Object" for my file and because in my invoice table I store the name as a string, I get an error here and I need to force the data_class => null .. which is bad, because if I edit a Invoice in the frontend for the upload field I get NULL, instead of the filename of the current file linked to the invoice.

With:

$builder->add('attachment', 'text')

I don't get the file input just a silly textbox BUT THIS TIME --with the name in it-- .. so how do I solve this? File Input widget and file name in it without a Document object ?!

And the second question ( I am merely at the point of throwing out all my application developed until now and move to laravel because I had a lot of "these kind of problems" ..doing simple things in symfony is almost always more complicated than in other frameworks..or maybe its my fault that I don't want to follow the guidelines and create a Document Entity?! What if I want flexibility and want to manage my database in another manner that doesn't fit in all these guidelines?)

So I am on the edit form action, I upload a new file (don't forget that I have the file set to $builder->add('attachment',file',array('data_class'=>null))

I can't get my attachment string name from the current invoice I am editing? !

public function editAction($id)
   ....
   $invoice = $em->getRepository('AppBundle:Invoice')->find($id);
   ..
    if ($form->isValid()) {
                
            $oldFileName=$invoice->getAttachment();  //this is null
            $oldFileName=$invoice->getId();   //this returns the invoice id
            $oldFileName=$invoice->getValue(); //returns invoice value

                echo 'old: '.$oldFileName.'<br/>';
                exit();
     }

So someone please tell me why I can't access my invoices property? Which is a string ?

I tried making a new instance I though that somehow if I create the form with the $invoice object it somehow links him to the attachment from the edit form

 if ($form->isValid()) {
    $sameInvoice= $em->getRepository('AppBundle:Invoice')->find(20); //hardcoded ID
    
                   $oldFileName=$sameInvoice->getAttachment();   //still null
                   $oldFileName=$sameInvoice->getId();   //returns 20
                    echo 'old: '.$oldFileName.'<br/>';
                    exit();

The only thing I wanted was, have a filename string in my invoice table, and test myself if the file exists in the path with that filename and if it exists, then delete it and upload the new one and so on.. why does it have to be so hard ??

Why do I have to create a entity ? Why do I have to alter my database structure (its not the case here..but what if the client doesn't want the database to be changed..so I can't insert this "Document" table).. Why can't the form builder show the data from invoice->attachment, I get it that because he needs a file data and he can't accept a string, but why aren't there guidelines for these simple tasks?!

enter image description here


Solution

  • Alright I finally managed to get it working:

    So the problem why it was NULL was because it did bind the $invoice instance to the form:

    $invoice = $em->getRepository('AppBundle:Invoice')->find($id);
    $form = $this->createForm(new InvoiceType($id), $invoice);
    

    After this block of code, all refferences like : $invoice->getAttachment();

    Are reffered to as the form invoice object not the actual object, so basically after this I can only call things like: "getClientOriginalName()" and would show me the new file that I uploaded in the edit form.

    To counter this I created a variable that stores that name initially before the $invoice object to get bind to the form

        $invoice = $em->getRepository('AppBundle:Invoice')->find($id);
        $oldFileName=$invoice->getAttachment();  //this is stil the object here I can see the record from the database
        $form = $this->createForm(new InvoiceType($id), $invoice);
      //here the $invoice->getAttachment(); returns null
    

    So now I have the old name and I can test it like:

     if ($form->isValid()) {
    
                    $fs=new Filesystem();
                    $newFile=$form['attachment']->getData();
                    $newFileName=$newFile->getClientOriginalName();
    
                    if($newFileName != $oldFileName)
                    {
                      //  if($fs->exists('files/'.$this->getUser()->getId().'/'.$oldFileName))
                      //      $fs->remove('files/'.$this->getUser()->getId().'/'.$oldFileName);
    
                        $sanitizedFilename=rand(1, 99999).'_'.$newFileName;
                        $dir='files/'.$this->getUser()->getId().'/';
                        $newFile->move($dir, $sanitizedFilename);
                        $invoice->setAttachment($sanitizedFilename);
                    }
    
                    $em->persist($invoice);
                    $em->flush();
    
                    return $this->redirect($this->generateUrl('my-invoices'));
                }
    

    For the other problem with the filename of the old file not appearing in the Edit Invoice Page I sent my variable to the view :

    return $this->render('AppBundle:Invoices:edit.html.twig', array(
                'oldFileName' => $oldFileName) 
    

    And put that value to the label of the input file widget using twig