I'm trying to upload a file to 3rd party endpoint, but I can't post the file directly from my form because the API requires an api_key which I can't expose to the end user. Therefore, my plan was to point the form to a controller/action and post the data from there. However, when I debug($this->request->data) from inside the controller, the file data is missing.
The form on the view:
echo $this->Form->create('Media', array('type'=>"file", 'url'=>array('controller'=>'media', 'action'=>'upload') ) );
echo $this->Form->input('name', array("name"=>"name") );
echo $this->Form->input('file', array('type'=>'file', "name"=>"file") );
echo $this->Form->input('project_id', array('type'=>'hidden', "name"=>"project_id", "value"=>$project["Project"]['hashed_id']) );
//THIS CANNOT BE HERE: echo $this->Form->input('api_password', array('type'=>'hidden', "name"=>"api_password", "value"=>'xxxxxxx') );
echo $this->Form->end("Submit");
Here's what what I see when I debug() the request data from the controller:
array(
'name' => 'Some Name',
'project_id' => 'dylh360omu',
)
What's going on here?
File upload data can only be found in CakeRequest::$data in case the input element name is passed in an array named data (which is the default when not defining a specific name manually), ie:
<input type='file' name='data[file]'>
In your case however, the element will look like this:
<input type='file' name='file'>
which will cause the files data to be put in CakeRequest::$params[form].
https://github.com/cakephp/cakephp/blob/2.4.0/lib/Cake/Network/CakeRequest.php#L346
So either change the name in the form accordingly:
$this->Form->input('file', array('type' => 'file', 'name' => 'data[file]'));
Or access the file data via CakeRequest::$params[form]:
debug($this->request->params['form']);
Nunser was right (as always)! The problem resulted from customizing the name of the input. When I remove the 'name'=>'...' from the options array, the file shows up as expected. This seems like a bug, but if someone has a better explanation I'd love to hear it.
Related
I am trying to pass the values of form inputs to a controller for validation. The values are populated in the view using an array. The problem is that I don't know how to get the necessary 'name' values from the array for the individual inputs in order to pass them through validation.
In the first view the form inputs are described this way:
<?php echo form_checkbox('study_items[]', 'Medical History', FALSE);
echo form_label('Medical History', 'Medical History');?>
<br>
<?php echo form_checkbox('study_items[]', 'Physical Exam', FALSE);
echo form_label('Physical Exam', 'Physical Exam');?>
<br>
<?php echo form_checkbox('study_items[]', 'Clinical Assessment', FALSE);
echo form_label('Clinical Assessment', 'Clinical Assessment');?>
The user only has to check the item(s) that apply to their specific need. This is submitted to the validation controller which, after successful validation, ONLY sends those items that were selected back to a view in an array like so:
$data['si_items'] = $this->input->post('study_items');
In the next view, the code for a sample input looks like this:
<?php foreach ($si_items as $si_item) {
echo $si_item. ' '. "$";
$data001 = array(
'name' => $si_item,
'id' => $si_item,
'value' => '',
'maxlength' => '10',
'size' => '50',
'style' => 'width:100px',
);
echo form_input($data001);
echo '<br>';
}
?>
and allows the user to enter a dollar amount for the items they selected to fit their need on the previous page.
As sample output of this portion of the code looks like this:
"Medical History $_______________"
"Physical Exam $_______________"
"Clinical Assessment $_______________"
where the blank is a textbox for entering the price of each item. So far, this all works perfectly to display each form input box and labels checked by the user in the previous view.
However, I'm at a loss as to how to get the 'name' for each individual input in order to validate it. The validation controller does not recognize '$si_items' as a name value. This has me stumped and there HAS to be a way to do this.
In my validation controller I want to check that each entry has a decimal value (i.e. 234.56) as the user's input.
Any ideas? Is there a more efficient way to do this?
we are missing swaths of code, but from what you have shown;\
$data['si_items'] = $this->input->post('study_items');
is the assignment of your study items (which is an array), meaning that the call in your foreach should not be
foreach ($si_items as $si_item) {
but rather
foreach ($data['si_items'] as $si_item) {
that or change your initial assignment to the following;
$si_items = $this->input->post('study_items');
I'm calling CHtml::ajaxlink like so:
<?php echo CHtml::ajaxLink('Add to a list',
$this->createUrl('itemList/ajaxadditem'),
array(
'onclick'=>'$("#addToListDialog").dialog("open"); return false;',
'type'=>'POST',
'update'=>'#addToListDialog',
'data' => 'js:{"product_id" : $("#productID").val()}'
),
array('id'=>'showAddToListDialog'));
?>
I don't know how to write the values of the AJAX options array dynamically. I'm using a workaround to get the value using JavaScript, $("#productID").val() and a hidden field.
I want to write something like:
'data' => 'js:{"product_id" : "$model->product_id"}'
But "$model->product_id" is entered as a literal string.
Can anyone give me a way to do this? My method won't actually solve the problem since I need to write this AJAX link multiple times on the fly.
Assuming your $model instance is available, you should be able to append it dynamically like below:
'data' => "js:{'product_id' : '{$model->product_id}'}"
For some reason my ajax form does not work if I change my form elements to hidden. It does how ever work if i change them to inputs instead. Why would that be?
Here is the view
<div id="price">
<?php
$this->Js->get('#phonepricearea');
echo $this->Form->create('offer', array('url' => '/PhoneKarma/PhoneQueries/ajaxOffer', 'class' => 'custom'));
echo $this->Form->hidden('phoneCapacity',array('value'=>''));
echo $this->Form->hidden('phoneCondition',array('value'=>''));
echo $this->Form->hidden('carrier',array('value'=>''));
echo $this->Js->submit('Check', array('class' => 'button expand',
'title' => 'Check',
'url' => array(
'action' => 'ajaxOffer'
),
'update' => '#price'
));
echo $this->Form->end();
?></div>
Controller
public function ajaxOffer($capacity=null, $condition = null , $carrier = null) {
if (!empty($this->data) && $this->request->is('ajax')) {
//do stuff this doesn't effect the code..
$this->render('ajaxOffer', 'ajax');
} else {
$this->set('offer', "0");
}
}
Javascript to change Value
$('#offerPhoneCapacity').val(id);
400 errors are usually security component blackholes. The documentation says it would issue 404 errors, but that's wrong, it throws a BadRequestException if not configured otherwise.
If an action is restricted by the Security Component it is black-holed
as an invalid request which will result in a 404 error by default. You
can configure this behavior by setting the
$this->Security->blackHoleCallback property to a callback function in
the controller.
SecurityComponent::blackHole(object $controller, string $error)
Black-hole an invalid request with a 404 error or a custom callback.
With no callback, the request will be exited. If a controller callback
is set to SecurityComponent::blackHoleCallback, it will be called and
passed any error information.
Your problem is probably caused by the security components form tampering prevention functionality. Hidden fields need to be static, because their values are used to genereate the security token, if the values change, the genereated comparision token will be different and thus the form will be treated as invalid.
By default SecurityComponent prevents users from tampering with forms.
It does this by working with FormHelper and tracking which files are
in a form. It also keeps track of the values of hidden input elements.
All of this data is combined and turned into a hash. When a form is
submitted, SecurityComponent will use the POST data to build the same
structure and compare the hash.
If you need to change hidden fields, then you have to define them in the unlockedFields property/option or by using the form helpers unlockField() method.
Examples (untested):
public $components = array
(
'Security' => array
(
'unlockedFields' => array
(
'Offer.phoneCapacity',
'Offer.phoneCondition',
'Offer.carrier'
)
)
);
public function beforeFilter()
{
$this->Security->unlockedFields => array
(
'Offer.phoneCapacity',
'Offer.phoneCondition',
'Offer.carrier'
);
}
$this->Form->unlockField('Offer.phoneCapacity');
$this->Form->unlockField('Offer.phoneCondition');
$this->Form->unlockField('Offer.carrier');
I have a small site which allows a user to enter values in a form and then either submit it directly or store the field values in a template to later submit it. To submit the form later, he can load the previously saved template. For that there are three buttons Load Template / Save Template / Submit form.
Because i am using the form validation built-in functionality from Codeigniter i run into problems when i want to populate the form with a template, which had been previously stored.
The form fields are all set up like
$name = array(
'name' => 'name',
'id' => 'name',
'value' => set_value('name', $form_field_values['name'])
);
The variable $form_field_values holds the values from either a loaded template in the case when a template has been loaded or the default values when the form is first loaded.
Initially the form is loaded with the default values. When i click on Load Template the values from the template are not chosen by set_value() because there were the default values in there before. What i want is to replace the values of the form fields with the ones from the template.
Do you have any idea how to do that in a clean approach? What i have done is to introduce a variable to skip the call to set_value() completely like:
$name= array(
'name' => 'name',
'id' => 'name',
'value' => $skip_form_validation ? $form_field_values['name'] : set_value('name', $form_field_values['name'])
);
Where $skip_form_validation is a variable set in the controller, based on what button was pressed. Form validation is skipped for saving/loading a template.
Codeigniter's set_value() function is a simple function which finds value in $_POST if value found then return else returns second argument, you can remove set_value() and write your own code for it. you can write $_POST['field_name'] if you want to populate value of POST data or add whatever value you want to add
Just use like this
$name = array(
'name' => 'name',
'id' => 'name',
'value' => $valueFromYourTemplate
);
You don't need to use set_value() function if you don't want to set POST values in the form
Assuming you retrieve the database fields and pass them to a data array in your controller.
$record = $this->data_model->get_record(array('uid' => $user_id), 'users');
if (!is_null($record)) {
$data['uname'] = $record->username;
$data['loc'] = $record->location;
}
where 'users' is the database table, and the uid is the id field of the table users.
In your form, do something like this
Hope it helps!
The Zend Form is proving to be a bit tricky for me, even as much as I am working with it lately...
I have this form and I am attempting to dynamically create the several checkboxes for it. It is working out alright, except I cannot seem to get the 'value' attribute to change.
In my Zend form class I have this snippet...
// psychotic symptoms
$this->addElement('checkbox', 'psychoticsymptom', array(
'label' => 'psychoticsymptom',
'name' => 'psychoticsymptom',
));
In my view (phtml) I am calling it like this...
<div class="element">
<?php // Psychotic Symptoms
$Criteria = new Criteria();
$Criteria->add( DictionaryPeer::CATEGORY, 'MAR: Psychotic Symptoms' );
$Criteria->addAscendingOrderByColumn( 'Ordinal' );
$this->PsychoticSymptomsList = DictionaryPeer::doSelect( $Criteria );
foreach( $this->PsychoticSymptomsList as $Symptom ) {
$form->psychoticsymptom->setValue($Symptom->getDictionaryId());
$form->psychoticsymptom->setAttrib('name', $Symptom->getWord());
echo $Symptom->getDictionaryId(); // prove my id is coming through... (it is)
$form->psychoticsymptom->getDecorator('label')->setTag(null);
echo $form->psychoticsymptom->renderViewHelper();
$form->psychoticsymptom->setLabel($Symptom->getWord());
echo $form->psychoticsymptom->renderLabel();
echo '<br />';
}
?>
</div>
Everything seems to be working fine, except the value attribute on each checkbox is rendering a value of '1'. I have tried moving the 'setValue' line to several different positions, as to set the value before the form element renders but I am having no luck getting this to work. It's worth any effort to me because I need to do the same type of operation in many areas of my application. I would have done this a bit different too, but I am re-factoring another application and am trying to keep some things unchanged (like the database for instance).
Any help is much appriciated
Thanks
you can try to overwrite the "checkedValue" and "uncheckedValue". check this reference
$this->addElement('checkbox', 'psychoticsymptom', array(
'label' => 'psychoticsymptom',
'name' => 'psychoticsymptom',
'checkedValue' => 'checked Value',
'uncheckedValue' => 'unchecked Value'
));
You seem to only have one psychoticsymptom element "checkbox" which your adding (changing) the value too for each $this->PsychoticSymptomsList.
Maybe you would be better off using a multicheckbox element instead.