i have a problem when coding my new Joomla component.
I have some input form in my custom joomla component (/components\com_custom\views\myview\tmpl\default.php )
<input type="text" class="form-control" name="jform[checkindate]" id="checkindate" value="<?php if (isset($post)) {echo $post; } else { echo 'Checkin date'; }?>">
Of courses, at the top i have this:
$jin = JFactory::getApplication()->input;
$post = $jin->get('checkindate', 'Checkin date', 'STR');
My point is to keep user post data if they faile in validation so they don't need to retype all the form, they only need to fix some error data before they can submit it again, but there is no success.
Could you please help me on this?
Thank you so much!
I'm assuming you are using Joomla jform for building forms
In jform, certain things need to take care if you want to maintain the form session.
Store the submitted form data in session - Before redirecting the user to form view after validation. you need to store the user data in user state. This is generally done in the controller file. This done by following way
$app = JFactory::getApplication();
$app->setUserState('componentname.formname.data', $data);
Please note that the first parameter is the key for your data which is stored in the user state. the second parameter is the Jinput data post by the user.
Load form data from the session if available - Till now we have saved the data in the session now we need to check whether form data available in session or not. This Is done in the load form data method written in the model.
`
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('componentname.formname.data', array());
if (empty($data))
{
// This is the my component function to load form data
$data = $this->getData();
}
return $data;
}
3 . If the form data saved successfully then don't forgot to clear it from the session.
$app->setUserState('componentname.formname.data', null);
Related
I am making a basic signup page using PHP Codeigniter.
On the signup page, I ask the user to select from a selection of categories (via a <select> html element). These categories are stored in a list in my MySQL Database.
My current method is to fetch this list from the DB when the user calls the function to load the page and then display it to them. However, if the user enter's incorrect data and the page must be reloaded with the validation errors, the variable that holds the data in the list seems to be cleared, and I must refetch the list data from the database before redisplaying the page.
I believe there's something in the documentation about how to set this variable to be permanently available but upon looking again, I had no luck in finding it.
Could anyone possibly point me in the right direction? It seems silly to me to have to need to refetch this data every time (I know that people won't be putting in wrong info often, but this will come in handy in a few situations).
NOTE: This is not an issue regarding remembering user selections.
this example is for a select drop down list using ci form helper
(i'm modifying this from another form so hopefully its all correct)
the Array of select values is: $categoryarray
the drop down field name is 'category'
the default value is $defaultcategory
a css class to style (bootstrap etc): $dropclass = 'class="input-medium"';
the line of code is:
form_dropdown('category',$categoryarray,set_value('category',$defaultcategory),$dropclass).form_error('category');
the form_error('category'); at the end is for showing a validation error message
and even though there is a default value - if the form fails validation from another field in the form - this will 'remember' what the user selected.
EDIT !
ok there is good and bad news.
bad news - if the categories are coming from a database then you need to get them again.
good news - CI remembers what category the user selected from the drop down list.
and the bad news actually isn't that big a deal - if you create the category array in your model. then its just one line of code to add to the validation.
// In the Model
function makedropdown() {
// get your category list
$cats = $this->getAllCategories() ;
$categoryarray = array();
// make the array
foreach ( $cats->result() as $row ) {
$categoryarray[$row->category] = $row->category ; }
return $categoryarray ;
}
someone has filled out the form, we run validation, validation fails. in the controller:
if ( $this->form_validation->run($formrules) == FALSE ) {
// get the categoryarray
$data['categoryarray'] = $this->categorymodel->makedropdown() ;
// load form again
$this->load->view( 'myform', $data ); }
So even though we are getting the categories again from the db to dynamically populate the select list - CI still remembers the users choice from the first time they did the form.
And what about a default category for the drop down? if its not going to change then it can be set as a config. if the category values are coming from a database and they can change - then the default category could be created in the model.
EDIT 2
gosh i always do this anyway so why didnt i think of it for this. so yeah this is yet another reason to make a specific method for showing your view
function _showCategoryForm(){
// get the categoryarray
$data['categoryarray'] = $this->categorymodel->makedropdown() ;
// anything else thats needed for the view
// load form view
$this->load->view( 'myform', $data ); }
NOW we dont have any repeated code, and its easy to customize the validation failure with an error message if needed.
// since i'm grinding on this - the validation should happen in a model
// and that method returns true or false
if ( $this->somemodel->validateCategoryForm() == FALSE ) {
// custom obnoxious error message
$this->formerrormessage = "What part of required is eluding you?" ;
$this->_showCategoryForm() ; }
This is much better because if the needs of your form changes - the change is only in one place. Also i added an underscore to remind us all that private methods are a good practice. And the form validation should be separate in a model, that is called by the controller.
You just need to set it as the default value, for example
<input type="text" name="username" value="<?php isset($_POST['username']) echo $username;?>" />
That way, $_POST['username'] will always be available.
stack: symfony2/doctrine2/php/mysql
a multipage form constist of two steps. each step is realized in a controller action.
in step1, the form is displayed. form-input is validated in the same action. if the form is valid the user should be redirected to the second step/action. in the second step the user has to confirm his input. after confirmation the data should be stored in the db.
thus form-entities/form-data are/is needed in the second step/action. however i do not want to store it in the db before confirmation.
do i really need to serialize all objects? to the session?
is there a better approach?
any suggestions?
First of all, I would recommend validating the input via JavaScript before posting and not in the controller action on the server.
If you don't want to serialize the data to the session you can simply pass it on to the next page when you receive it in the first action and then post it to the second action, I'm imagining something like this:
firstAction() {
$exampleData = $_POST['exampleData'];
// Do whatever you need, then pass the data on to the next page
return $this->render('SomeBundle:Views:secondPage.html.php',
array('exampleData' => $exampleData));
On the second page you then just have to access $exampleData with JavaScript and best put it in some hidden input field inside the form.
<!-- secondPage.html.php -->
<script type="text/javascript">
var exampleData = <?php echo $exampleData ?>;
$('#hiddenInput').val(exampleData);
</script>
The second controller action will then receive $exampleData as well without having it serialized in the session.
Sorry if there are any syntax errors, haven't used symfony2 in a while :)
tried to use serialization, but entities are quite complex with "many" associations. thus serialization is too slow. even after detaching.
first solution (simplified):
store the POST variables to the session inside the first step/action.
$postParams = $this->getRequest()->request;
$session = $this->getRequest()->getSession();
if (!$session) {
$session = new Session();
}
$session->set($sessionKey, $postParams);
in the second step/action i used the form to repopulate my entity.
$cancellation = $manager->initCancellationSomehow();
$session = $this->getRequest()->getSession();
if (!$session) {
$session = new Session();
}
$parameterBag = $session->get($sessionKey);
$cancellation = $this->getCancellation($customerId);
$form = $this->createForm(
new CancellationType(),
$cancellation,
array(
'em' => $this->getDoctrine()->getManager())
);
$form->bind($parameterBag->get('form'));
[..]
second solution:
well my first thought was to store cancellation in the db. therefore i added a state attribute (active/temp/..). unconfirmed cancellations get marked as temp. if the user confirms the state gets changed form temp to active. temp collections get deleted after on hour by a garbarge collector which runs at a low priority.
i like the second solution because the user has to confirm the final cancellation, which is already stored in the db. if the frontend does not work as expected the user will likely notice corrupted cancellations (e.g. wrong entries selected). if he confirms, only the state is changed. feels safe. in the first solution the user confirms what should be stored in the db, but isn't till now. feels unsecure.
In Codeigniter I do this
$p=$this->input->post();
to get all objects posted but I don't know if there is something similar in cakephp to get all posted variables from a form ? I am writing a function to get posted password and save it into database in place of the old password recorded there.
I use native php to get 'posted' variables from a form, (I am not familiar with cakephp form usage) that is why, so instead of using $_POST['sssss'] what should I do now ?
Thank you for any help.
$value = $this->request->data('key');
Please for further reference, read the manual. It's so much easier and better for yourself to figure it out by yourself.
http://book.cakephp.org/2.0/en/controllers/request-response.html#accessing-post-data
for the GET method
$this->request->query['category-name'];
and POST method
$this->request->data
http://book.cakephp.org/2.0/en/controllers/request-response.html#accessing-querystring-parameters
You can check if posted a form by using
if (!empty($this->data)) {
print_r($this->data);
}
The Post data must be in data to show up in $this->request->data.
Example:
// input field
<input type="text" name="data[foo]" value="bar" />
// in your controller
debug($this->request->data);
To check if posted a form, please use:
if ($this->request->is('post')) {
pr($this->request->data);
}
If you want to get a specific field of the table can move so:
if($this->data["Objetorastreavel"]["id"]){
}
It checks only the ID Objetorestraeval if you want to pick only one field and not post the whole page.
You should able to access form post data with:
For CakePHP 2.x
if ($this->request->is('post')) {
pr($this->request->data);
}
For CakePHP 3.4.x
if ($this->request->is('post')) {
pr($this->request->getData());
}
Documentation for CakePHP 3
You can use following to retrieve post/get data in CakePHP
For post data:
$this->request->data;
For get data:
$this->request->query;
I would like to make a form I have in my website self referencing. Or if that's not an option, how would I go for, for example, showing the results of a search I make in my site?
I have a site in which you search for places and it returns a list of places for your preferences. At the moment my script creates a new node every time a user searches but this isn't convenient anymore. How do I change it so that the page content is changed and I see the results instead of the search form?
Thanks,
You should redirect your form to a page passing a query string with the string of what the user searched and then use $_GET['search_param'] in your search/restuls page to handle what will be displayed to the user.
function yourform_form($form_state) {
$form = array();
//$form['your_search_field']
$form['#submit'][] = 'yourform_form_submit';
return $form;
}
function yourform_form_submit(&$form, $form_state) {
$query = 'search_param='. $form_state['values']['your_search_field'];
drupal_goto('search/results', query);
}
If you're using Drupal 7 your submit function should look like:
function yourform_form_submit(&$form, $form_state) {
$options['query']['search_param'] = $form_state['values']['your_search_field'];
drupal_goto('search/results', $options);
}
After you submit you should be redirected to http://yoursite.com/search/results?search_param=my_search_value
Note that this technique is used by popular search engines:
https://www.google.com/search?q=my_search_value
Your form should include $form['#action'] to lead you to specific page after submit:
function example_form($form_state) {
$form = array();
//your form code
//...
$form['#action'] = url('search/results');
return $form;
}
On submitting form (example_form_submit) you should take all your values and save them to cookies using user_cookie_save function and on your page you can use this cookies.
You also could serialize your values to deal only with one cookie if you want, and then unserialize them on your page. You can delete cookie using user_cookie_delete function.
You should define path search/results where you could take those cookies data and manipulate with it.
On my website, I have user accounts that are configurable with forms that allow users to update everything from first and last names to privacy settings. I use the following function to update the database with that input. (Note that the following code uses WordPress-specific features.)
function update_account() {
global $current_user; get_currentuserinfo();
require_once( ABSPATH . WPINC . '/registration.php' );
$uid = $current_user->ID;
// First Name
if(isset($_POST['first_name']) && $_POST['first_name'] <> $current_user->first_name) {
wp_update_user( array(
'ID' => $uid, 'first_name' => esc_attr($_POST['first_name'])
));
}
// ...and so on 43 more times...
}
This feels like the wrong way to process forms. This also looks like it will negatively impact server performance when there are multiple users and frequent updates, given that the if-then-else conditions for every field, even fields not on a particular page, force checking each field for input.
Moreover, since form data can be expected to remain relatively constant, I added the <> operator to prevent the function from updating fields where there has not been any change, but I suspect this also means that every field is still evaluated for change. To make matters worse, adding new fields -- there are already 44 fields in total -- is an unwieldy process.
What's a better way to process form data?
Keep an array of the fields you will be processing with this code, and iterate over it. This works if all your attributes are strings, for example. If you have different data types such as boolean flags to handle differently from the strings, you may wish to group them into their own array.
// All the fields you wish to process are in this array
$fields = array('first_name', 'last_name', 'others',...'others99');
// Loop over the array and process each field with the same block
foreach ($fields as $field) {
if(isset($_POST[$field]) && $_POST[$field] != $current_user->{$field}) {
wp_update_user( array(
'ID' => $uid, $field => esc_attr($_POST[$field])
));
}
}
There's a lot of things missing with your implementation. I don't know what kinds of data you're allowing the user to manipulate but most usually have some kind of requirements to be acceptable. Like not having certain characters, not being blank, etc. I don't see any validation occurring, so how do you handle values that might be undesirable? And what happens when you receive bad data? How do you inform the user of the bad data and prompt them to correct it?
If we abstract the situation a bit we can come up with generalizations and implement an appropriate solution.
Basically form fields [can] have a default value, a user specified value [on form review], validation requirements and validation errors [with messages]. A form is a collection of fields that upon form submit needs to be validated and if invalid, re-displayed to the user with instructive corrective prompts.
If we create a form class that encapsulates the above logic we can instantiate and use it to pass around our controller/views. Oops, I was just assuming you were using an Model/View/Controller type framework, and I'm not really familiar with wordPress so I don't know if that is exactly applicable. But the principle still applies. On the page where you both display or process the form, here's some pseudo logic how how it might look.
function update_account()
{
// initialize a new form class
$form = new UserAccountInfoForm();
// give the form to your view for rendering
$this->view->form = $form;
// check if form was posted [however your framework provides this check]
if(!Is_Post())
return $this->render('accountform.phtml');
// check if posted form data validates
if(!$form->isValid($_POST))
{
// if the form didn't validate re-display the form
// the view takes care of displaying errors, with the help of its
// copy of the $form object
return $this->render('accountform.phtml');
}
// form validated, so we can use the supplied values and update the db
$values = $form->getValues(); // returns an array of ['fieldname'=>'value']
// escape the values of the array
EscapeArrayValues($values);
// update db
wp_update_user($values);
// inform the user of successful update via flash message
$this->flashMessage('Successfully updated profile');
// go back to main profile page
$this->redirect('/profile');
That makes your controller relatively clean an easy to work with. The view gets some love and care to, utilizing the $form value to display the form correctly. Technically, you can implement a method in the form class to give you the form html, but for simplicity I'm just going to assume your form html is manually coded in accountform.phtml and it just uses $form to get field info
<form action='post'>
<label>first name</label> <input class='<?=$this->form->getElement('first_name')->hasError() ? "invalid":""?>' type='text' name='first_name' value="<?=$this->form->getElement('first_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('first_name')->getError()?></span><br/>
<label>last name</label> <input class='<?=$this->form->getElement('last_name')->hasError() ? "invalid":""?>' type='text' name='last_name' value="<?=$this->form->getElement('last_name')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('last_name')->getError()?></span><br/>
<label>other</label> <input class='<?=$this->form->getElement('other')->hasError() ? "invalid":""?>' type='text' name='other' value="<?=$this->form->getElement('other')->getValue()"/> <span class='errmsg'><?=$this->form->getElement('other')->getError()?></span><br/>
<input type='submit' value='submit'/>
</form>
Here the pseudo code relies on the form class method "getElement" which returns the field class instance for the specified field name (which would be created an initialized in the constructor of your form class). Then on the field class methods "hasError" and "getError" to check if the field validated correctly. If the form has not be submitted yet, then these return false and blank, but if the form was posted and invalid, then they will have been set appropriately in the validate method when it was called. Also "getValue" would return either the value supplied by the user when the form was submitted, or if the form has not been submitted, the default value as specified when the field class was instantiated and initialized.
Obviously this pseudo code is relying on a lot of magic that you'd have to implement if you roll your own solution--and it's certainly doable. However, at this point I'll direct you to the Zend Framework Zend_Form components. You can use zend framework components by themselves without having to utilize the entire framework and application structure too. You might also find similar form component solutions from other frameworks but I wouldn't know about those (we are a Zend Framework shop at my work place).
Hopefully this hasn't been too complicated, and you know where to go from here. Of course just ask if you need any clarification.