Soma Posted December 5, 2014 Share Posted December 5, 2014 Maybe this helps someone. Nerd alert! Currently building a shop module for a project, where I was looking for a easy way to handle/store form data in session and later repopulate it easily using form API. It can be very tedious to do that manually grab the fields, store in session repopulate form. So I found a way to do it "automatically" by serializing form object and build a name => value array that I store in session, then retrieve the array later and convert it to WireInputData as it is required for form object to process. Further I needed to turn of CSRF temporarely to get around error when populating the form object. Here a example code for those interested. // generate $form // when sent if($input->post->send) { // process form $form->processInput($input->post); // if no errors if(!count($form->getErrors())){ // serialize form values and store in "shop" session namespace $formfields = $form->getAll(); $formdataKeys = $formfields->explode(function($item, $key){ return $item->name; }); $formdataValues = $formfields->explode(function($item, $key){ return $item->value; }); $formdata = array_combine($formdataKeys, $formdataValues); $session->setFor("shop", "userformdata", $formdata ); $session->redirect("nextpageurl"); } } else { // if session formdata found repopulate form object if($formdata = $session->getFor("shop", "userformdata")){ $formdataInput = new WireInputData($formdata); $form->protectCSRF = false; // to not get a CSRF validation error $form->processInput($formdataInput); // fills in form and validates it $form->protectCSRF = true; } } return $form->render(); 11 Link to comment Share on other sites More sharing options...
Soma Posted December 5, 2014 Author Share Posted December 5, 2014 For security. I wanted to add, that the stored values in the array are not entity encoded and if you don't strip tags they're stored as entered, so you'd have to take care of that and entity encode with htmlspecialchars() them before printing them somewhere or use a sanitizer. When using the form render() it already takes care of that when populating the inputfields. It's still possible you have or want to allow tags, so it's a question of what you do with the data. Always be careful and if in doubt ask a experienced developer. foreach($formdata as $name => $val){ ... $out .= "<td>" . htmlspecialchars($val, ENT_QUOTES, "UTF-8") . "</td>"; ... } You could add a strip tags when getting the values like this: $formdataValues = $formfields->explode(function($item, $key){ return strip_tags($item->value); }); 1 Link to comment Share on other sites More sharing options...
owzim Posted December 6, 2014 Share Posted December 6, 2014 Smells like a ProcessWire Recipe Or make a module out of it? 1 Link to comment Share on other sites More sharing options...
Soma Posted December 6, 2014 Author Share Posted December 6, 2014 Let's see what happens. Of course alternatively, serializing the form object also works quite simply with a foreach, without using PW's WireArray::explode() which is fun anyway. After all the trick here is the $form->getAll(), which returns a InputfieldWrapper containing a flat array of only the fields whithout fieldsets and nested wrappers. And example of how to populate the form directly without using processInput($data), which requires to toggle the CSRF and the form validates and show errors when rendering the form. So setting values to the form object using $form->get(field)->attr("value", $value) does that "silently" and it doesn't trigger any validation thus not show errors when initially loading the form. if($input->post->send) { $form->processInput($input->post); if(!count($form->getErrors())){ $exclude = array("send"); // skip fields by name foreach($form->getAll() as $field) { if(in_array($field->name, $exclude)) continue; $formdata[$field->name] = strip_tags($field->value); } $session->setFor("shop", "userformdata", $formdata ); $session->redirect($this->page->url . $this->nextStepSegment); } } else { // populate data to form inputfields without using processInput(), which processes the form if($formdata = $session->getFor("shop", "userformdata")){ foreach($formdata as $name => $value) $form->get($name)->attr("value", $value); } } return $form->render(); 3 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now