4

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

I refuse to use some 3rd party plugin for file uploads, and refuse to creat 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 collumb name "attachment", I want to store here its sanitized name (eg: 123421_filename.jpg ), the addition form and upload went well.

code here:

//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 folow 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

doglover1337
  • 146
  • 4
  • 18

2 Answers2

1

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

doglover1337
  • 146
  • 4
  • 18
0

Remain calm. You are making this much harder then it needs to be.

myControllerAction()
{
    // No need for an object, an array works fine
    $model = array(
        'invoice' => $invoice,
        'attachment' => null
    );

    $builder = $this->createFormBuilder($model);

    $builder->setAction($this->generateUrl('cerad_game_schedule_import'));
    $builder->setMethod('POST');

    $builder->add('attachment', 'file');
    $builder->add('invoice', new InvoiceType());

    $builder->add('import', 'submit', array(
        'label' => 'Import From File',
        'attr' => array('class' => 'import'),
    ));        
    $form = $builder->getForm();

    $form->handleRequest($request);

    if ($form->isValid())
    {   
        $model = $form->getData();
        $file = $model['attachment']; // The file object is built by the form processor

        if (!$file->isValid())
        {
            $model['results'] = sprintf("Max file size %d %d Valid: %d, Error: %d<br />\n",
            $file->getMaxFilesize(), // Returns null?
            $file->getClientSize(),
            $file->isValid(), 
            $file->getError());
            die($model['results'];
        }
        $importFilePath = $file->getPathname();
        $clientFileName = $file->getClientOriginalName();

        // Xfer info to the invoice object and update

    }
Cerad
  • 48,157
  • 8
  • 90
  • 92
  • I am not really sure what $importFilePath = $file->getPathname(); $clientFileName = $file->getClientOriginalName(); do.. But as I can see is this a edit action or an add action? My main problem is that when I access the edit invoice page i can't see the filename of the atachment he got when the invoice was added. And the second one, that I can't get from my database the filename I saved when I created the invoice.. my test is something like": if($newFileName!=$oldFileName) //if the old file is not the same with the new one { delete the old one } – doglover1337 Feb 24 '15 at 20:37
  • They are both in the Edit Action of a Invoice .. showing filename uploaded from db (frontend) and.. getting the $invoice->attachment field (where I have stored the filename of the first file uploaded with the invoice) .. get that filename test if its != from the new file from the edit form, and if its != then delete the old file, add the new one with $file->move() and update the invoice record with the new filename in the attachment field – doglover1337 Feb 24 '15 at 20:49
  • The importFilePath is where the file has been uploaded to on the server. You would open this path to read the contents. Your code uses the move() method so importFilePath is not relevant. The clientFileName is the name of whatever file was uploaded from the client. Just the name, not the complete client path. It's all documented here: http://api.symfony.com/2.6/Symfony/Component/HttpFoundation/File/UploadedFile.html. – Cerad Feb 24 '15 at 21:03
  • The edit workflow is up to you. I would not check file names. I would just assume that if the user selects a local file then they want to swap it for the old one. No selected file means no change wanted. – Cerad Feb 24 '15 at 21:04
  • Ok this logic is good, but I have the files stored on the hard drive, I update the new filename in the database, but how do I delete the old file from the hard drive if I can't select the attachment name initially to know what to delete from the files directory? – doglover1337 Feb 24 '15 at 21:21