I am trying to achieve the following based on this example:
http://symfony.com/doc/current/cookbook/doctrine/file_uploads.html
I have a virtual filed that is going to be used for uploading a file. Everything works perfect for the upload process. However, the file field in the form is always required probably because of
/**
* #Assert\Image(maxSize="1000000")
*/
public $image_virtual;
Is there any way to have a File or Image requirement only when the $image_virtual is filled? I want to be able to save the form even if the user doesn't input an Image
Basically it should work totally fine like that as long as you don't insert a
/**
* #Assert\NotBlank
*/
into your entity.
You have to check that your field is not required in your formbuilder, like this:
$builder->add('image_virtual', 'file',
array(
'required' => false
)
);
Related
im learning about angularjs and laravel. Basically i use angular to fetch my data in the forms and than send it to laravel to grab my variables and than create the record, the problem is with one input field (mobile), if i fill the mobile input it doesnt give me any problems, but if i leave it empty (since is not required input) it fails to create the record and give me a undefined index.
How can i make in Laravel to create anyway the record if one variable in my case is empty or not created?
php code:
public function registerUser($inputData)
{
$user = \DB::transaction(function () use ($inputData)
{
$user = User::create([
'email' => $inputData['user']['email'],
'name' => $inputData['user']['name'],
'surname' => $inputData['user']['surname'],
'mobilephone' => $inputData['user']['mobilephone'],
'birth_date' => Carbon::createFromFormat('d-m-Y', $inputData['user']['birth_date']),
]);
$user->save();
//Return the User
return $user;
});
//Return the User instance
return $user;
}
From what you are describing, when you don't fill in the mobile number the front end doesn't send an object which includes "$inputData['user']['mobilephone']". Which would cause an error in the script and prevent it from running. Please post the angular code responsible for transmitting the user information.
If my assumption is correct, you either need to check that these properties all exist in the $inputData before referencing them or have the front end add a dummy value when no value is provided.
OR What ever is holding the record (MySQL or whatever) may not allow this field to be null which would again prevent the insertion. But your description suggests this isn't it.
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?!
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
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
}
Was checking out this tutorial "http://book.cakephp.org/2.0/en/models/data-validation.html" only seem to explain validating on form fields.
So what If I want to validate params or input data.
If I have this controller, where I want to validate a this "campaignId"?:
public function agency($campaignId = null){
if ($this->request->is('get')){
$campaignId;
...
}
CakePHP Model Data Validation is validation of the data, regardless of where it comes from.
If you create an array of data, eg:
$article = array(
'title' => 'Pizza is the Best Food on Earth',
'byline' => 'Dave from StackOverflow',
'content' => 'Pizza is awesome. I love it.'
);
Then try to save it:
$this->Article->save($article);
The Model's validation will kick in and validate (or invalidate) the data.
The most common way data is entered is via a form, but - beyond that, validation is not directly tied to using a form(s).
I want to edit a record in CakePhp without deleting the saved path of an uploaded jpg file. Right now when I edit the record it deletes the saved file path.
The approach I think would work is to do a logic check in the form to check if the field is empty or not. Display the saved file path if it's not empty or show an empty path if it is. Would this be the best way to update the record?
I'm using Miles Johnson's uploader plugin for uploading files.
Here's the code within the form:
<?php
if (!empty ($slider ['Slider']['bgImg']));
echo $slider ['bgImg'];
else
echo $form->input('file', array('type' => 'file'));
?>
This logic should be in the controller, strictly speaking.
In my apps with files and edit capabilities, I will show a file field and a link/thumbnail of the image in question on the edit form.
my approach uses my own uploader, so your results may vary, but essentially:
if (!empty($this->data)) {
$file_object = $this->data['Listing']['featured_image'];
$image_data=$this->Upload->do_upload($file_object, 'img/uploads/');
if($image_data){
$this->data['Listing']['featured_image'] = $image_data['name'];
} else {
unset($this->data['Listing']['featured_image']);
}
$this->Listing->save($this->data)
and in my upload component, I have this:
public function do_upload($file_object, $location='img/uploads/') {
/**
* No file was uploaded
*/
if($file_object['error']==4) {
return false;
}
// carry on uploading
So essentially; I pass my upload component the $file_object, which is from the form. I then do a simple test, using the default set of error codes to see if the file is empty (4). If it's empty, I return false. (you could return errors etc, but this was my approach).
after the upload call, I check the return value, and if the file was uploaded successfully, I can then set the field in my model. (the file name, in my case) - you may want to store the path as well, for instance.
If it's false - it means there was no file; so I unset the value from the array.
Because the field does not exist in the array, cake will not attempt to overwrite existing data - it simply ignores it; allowing the old value to stay untouched.
I have a bunch of name/email fields in my form like this:
data[Friend][0][name]
data[Friend][1][name]
data[Friend][2][name]
etc.
and
data[Friend][0][email]
data[Friend][1][email]
data[Friend][2][email]
etc.
I have a custom validation rule on each one that checks to see if the corresponding field is filled in. Ie. if data[Friend][2][name] then data[Friend][2][email] MUST be filled in.
FYI, heres what one of the two rules look like:
My form validation rule: ( I have an email validation too but that's irrelevant here)
'name' => array(
'checkEmail' => array(
'rule' => 'hasEmail',
'message' => 'You must fill in the name field',
'last' => true
)
)
My custom rule code:
function hasEmail($data){
$name = array_values($data);
$name = $name[0];
if(strlen($name) == 0){
return empty($this->data['Friend']['email']);
}
return true;
}
I need to make it so that one of the pairs should be filled in as a minimum. It can be any as long as the indexes correspond.
I can't figure a way, as if I set the form rule to be required or allowEmpty false, it fails on ALL empty fields. How can I check for the existence of 1 pair and if present, carry on?
Also, I need to strip out all of the remaining empty [Friend] fields, so my saveAll() doesn't save a load of empty rows, but I think I can handle that part using extract in my controller. The main problem is this validation. Thanks.
I would have a look at the Model::beforeValidate callback (API).
Using this callback to output debug information should help you figure out how many times it fires and what data is available to the model on each call.
With this information, you could then create a flag when you find your first matching pair, and tamper with either the Model::validates array or the Model::data array to bypass subsequent validation attempts.
As for your last point, you may be able to use Set::filter to easily remove blank fields from your data set.