I have a form in my project which is very simple.
It is a textbox with a label, that's it.
But when I try to get the data from those textboxes, it returns NULL.
get($id) and get($id)->getData(), both return NULL.
It's a form without any class attached to it, just to keep it simple.
The purpose of this form is to adjust a number.
What am I doing wrong? Or is there a better way to solve this?
public function makenAction()
{
$em = $this->getDoctrine()->getManager();
$orderregels = $this->getRequest()->getSession()->get('orderregelz')->getOrderregels();
$overzicht = $this->createFormBuilder();
foreach($orderregels as $value)
{
/*
* getting some values from database
*/
$overzicht->add($temp->getOrderregelD(),"text",array('label'=>$tmpcompleet));
}
$overzicht->add('Verzenden','submit');
$request = $this->getRequest();
if ($request->getMethod() == 'POST')
{
$data = array();
foreach ($orderregels as $value)
{
$data[] = $overzicht->get($value);
}
}
this is the way you get data from the request
GET
$value = $request->query->get("input_name");
POST
$value = $request->request->get("input_name");
Otherwise you can simply do:
$formData = $overzicht->getData();
and then access the values like:
$foo = $formData['foo'];
To directly access all the values of a specified form, do:
$formData = $this->getRequest()->request->get('form');
After all, you should to bind the request to form.
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
var_dump($editForm->getData()); die;
}
doc
Related
I have a Post entity and PostType.
Post entity have field $requireModeration it means someone must check this post and approve it before it can be published.
When I'm editing post I want to compare old post value and new post value. And if value is changed I also want to change requireModeration flag to true.
Can I do it through form events?
Something like this:
public function postSubmit(FormEvent $event)
{
$newPost = $event->getData();
$newContent = $post->getContent(); // return new contant of post
$oldPost = ... // here I want to get old post
$oldContent = $oldPost->getContent();
if($newContent != $oldContent) {
// ...
}
}
But unfortunately I can get only new, just sent data through FormEvent object.
You should use Doctrine's lifecycle events and UnitOfWork for this instead of Form events (I assume that you use Doctrine at your project).
Add preUpdate listener to your Post entity and do something like:
$uow = $em->getUnitOfWork();
$changeset = $uow->getEntityChangeSet($entity);
In $changeset variable you will have fields list that was changed in the $entity during current request with their old and new values.
public function postSubmit(FormEvent $event)
{
$newPost = $event->getData();
$newContent = $newPost->getContent();
$uow = $this->em->getUnitOfWork();
$oldPost = $uow->getOriginalEntityData($post);
$oldContent = $OriginalEntityData["content"];
if($newContent != $oldContent) {
// ...
}
}
I'm a Zend Framework newbie and I'm trying to retrieve some values to update the database. I have the following code in the controller. Populating the form works just fine, as does updating the db with some hard-coded values. My problem lies in trying to retrieve an updated value from the form, see the $first_name variable. It gives me a fatal error.
My question: How do I retrieve an updated value from the form?
public function editAction() {
$view = $this->view;
//get the application
$application_id = $this->getRequest()->getParam('id');
$application = $this->getApplication($application_id);
//get the applicant
$applicant_id = $application->applicant_id;
$applicant = $this->getApplicant($applicant_id);
if ($this->getRequest()->isPost()) {
if ($this->getRequest()->getPost('Save')) {
$applicants_table = new Applicants();
$first_name = $form->getValue('applicant_first_name');
$update_data = array ('first_name' => 'NewFirstName',
'last_name' => 'NewLastName');
$where = array('applicant_id = ?' => 16);
$applicants_table->update($update_data, $where);
}
$url = 'applications/list';
$this->_redirect($url);
} else { //populate the form
//applicant data
$applicant_data = array();
$applicant_array = $applicant->toArray();
foreach ($applicant_array as $field => $value) {
$applicant_data['applicant_'.$field] = $value;
}
$form = new FormEdit();
$form->populate($applicant_data);
$this->view->form = $form;
}
}
First off, your example has a problem here:
$first_name = $form->getValue('applicant_first_name');
...your $form isn't created yet, thus the fatal error; you are calling getValue() on a non-object.
Once you get that squared away, you can populate the form with posted data by calling the isValid method on the $form with request data. Here's a quick example:
// setup $application_data
$form = new FormEdit();
$form->populate($applicant_data);
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$first_name = $form->getValue('applicant_first_name');
// save data to the database ...
}
}
I'm having a problem when I try to save the form's information into the database. My form doesn't seem to be valid, even after manually setting the Theater's id for every theater in the chosen Network.
Here's the related part of my module's actions.class.php :
Here's executeCreate():
public function executeCreate(sfWebRequest $request) {
$this->form = $this->configuration->getForm();
$this->showing = $this->form->getObject();
$this->processCreateForm($request, $this->form);
$this->setTemplate('new');
}
and now processCreateForm():
protected function processCreateForm(sfWebRequest $request, sfForm $form) {
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
$form_name = $form->getName();
$parameters = $request->getParameter($form_name);
$network_id = $parameters['network_id'];
$theaters_list = Doctrine_Query::create()
[...]
->execute();
foreach ($theaters_list as $theater) {
$form->getObject()->setTheaterId($theater->theater_id);
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid()) {
$showing = $form->save();
} else {
foreach ($form->getErrorSchema()->getErrors() as $key => $error) {
echo '<p>' . $key . ': ' . $error . '</p>';
}
}
}
$this->getUser()->setFlash('update_success', true);
$this->setTemplate('new');
}
Here's the output :
Thank you for your help
There are two strange things going on here which I think break your code.
You run the bind() method twice which might be resetting your values on the object.
I don't think that the getObject() method returns the object by reference.
So when you run:
$form->getObject()->setX($val);
$form->save();
then you update the field of the object returned by the form, but then save the original object which is still bound to the form.
Try doing something like this:
$myObject = $form->updateObject()->getObject();
$myObject->setX($value);
$myObject->save();
The updateObject() is important if you use the form to edit an existing object, not to create a new one. Without this you will get the old values of the object.
If you want to run it in a loop you can loop only the setting and saving part. So you would have something like this in your processCreateForm:
protected function processCreateForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid()) { //You can check the validity of your form at this point.
//Create $theatersList
...
$myObject = $form->updateObject();
foreach ($theatersList as $theater) {
$myObject->setTheaterId($theater->theater_id);
$showing = $myObject->save();
//Do something with $showing
}
} else {
//Print the errors.
}
}
Using this code you can unset the widget for theatre_id in your form as it should not be set by the user and does not have to be part of the form validation.
EDIT
Some changes to the code:
protected function processCreateForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
if ($form->isValid()) { //You can check the validity of your form at this point.
//Create $theatersList
...
$myObject = $form->updateObject();
$myObjectVars = $myObject->toArray();
foreach ($theatersList as $theater) {
$myNewObject = new SomeClass();
$myNewObject->fromArray($myObjectVars);
$myNewObject->setTheaterId($theater->theater_id);
$showing = $myNewObject->save();
//Do something with $showing
$myNewObject->free();
unset($myNewObject);
}
} else {
//Print the errors.
}
}
I have following action to display a form
public function showformAction() {
$this->view->form = new Form_MyForm();
$this->view->form->setAction( 'submitform' );
}
above action shows a form successfully with only one textarea and submit button.
And I am using following action to submit above form:
public function submitformAction() {
$form = new Form_MyForm();
$request = $this->getRequest();
if ( $request->isPost() ) {
$values = $form->getValues();
print_r($values);die();
} else {
echo 'Invalid Form';
}
}
Above action is showing following output:
Array ( [myfield] => )
It means it is not posting values correctly and always shows empty array or I am not getting posted values correctly. How to post values to submitformAction().
Thanks
I think you must use the isValid() before accessing the values of a submitted form, because it's right there that the values are checked and valorized
public function submitformAction() {
$form = new Form_MyForm();
$request = $this->getRequest();
if ( $request->isPost() ) {
if ($form->isValid( $request->getPost() )) {
$values = $form->getValues();
print_r($values);die();
}
} else {
echo 'Invalid Form';
}
}
In complement to #VAShhh response. With some more details:
You need to do two things, populate your form fields with the POSTed data and applying security filters and validators to that data. Zend_Form provides one simple function which perform both, it's isValid($data).
So you should:
build your form
test you are in a POST request
populate & filter & validate this data
either handle the fact in can be invalid and re-show the form wich is now
decorated with Errors OR retrieve valid data from the form
So you should get:
function submitformAction() {
$form = new Form_MyForm();
$request = $this->getRequest();
if ( $request->isPost() ) {
if (!$form->isValid($request->getPost())) {
$this->view->form = $form;
// here maybe you could connect to the same view script as your first action
// another solution is to use only one action for showform & submitform actions
// and detect the fact it's not a post to do the showform part
} else {
// values are secure if filters are on each form element
// and they are valid if all validators are set
$securizedvalues = $form->getValues();
// temporary debug
print_r($securizedvalues);die();
// here the nice thing to do at the end, after the job is quite
// certainly a REDIRECT with a code 303 (Redirect after POSt)
$redirector = $this->_helper->getHelper('Redirector');
$redirector->setCode(303)
->setExit(true)
->setGotoSimple('newaction','acontroller','amodule');
$redirector->redirectAndExit();
} else {
throw new Zend_Exception('Invalid Method');
}
}
And as said in the code re-showing the form you shoudl really try to use the same function for both showing and handling POST as a lot of steps are really the same:
building the form
showing it in the view in case of errors
By detecting the request is a POST you can detect you are in the POST handling case.
I wonder how Zend_Form validates inputs, I mean how does it know which input fields to validate. I looked to php globals($_POST, $_GET) and I didn't see anything set as an identifier(for example ) in order to know how validate. Can anyone suggest me any guide for this stuff?
Well, the best option to find out is to look at the code of Zend_Form:
/**
* Validate the form
*
* #param array $data
* #return boolean
*/
public function isValid($data)
{
if (!is_array($data)) {
require_once 'Zend/Form/Exception.php';
throw new Zend_Form_Exception(__METHOD__ . ' expects an array');
}
$translator = $this->getTranslator();
$valid = true;
$eBelongTo = null;
if ($this->isArray()) {
$eBelongTo = $this->getElementsBelongTo();
$data = $this->_dissolveArrayValue($data, $eBelongTo);
}
$context = $data;
foreach ($this->getElements() as $key => $element) {
if (null !== $translator && $this->hasTranslator()
&& !$element->hasTranslator()) {
$element->setTranslator($translator);
}
$check = $data;
if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) {
$check = $this->_dissolveArrayValue($data, $belongsTo);
}
if (!isset($check[$key])) {
$valid = $element->isValid(null, $context) && $valid;
} else {
$valid = $element->isValid($check[$key], $context) && $valid;
$data = $this->_dissolveArrayUnsetKey($data, $belongsTo, $key);
}
}
foreach ($this->getSubForms() as $key => $form) {
if (null !== $translator && !$form->hasTranslator()) {
$form->setTranslator($translator);
}
if (isset($data[$key]) && !$form->isArray()) {
$valid = $form->isValid($data[$key]) && $valid;
} else {
$valid = $form->isValid($data) && $valid;
}
}
$this->_errorsExist = !$valid;
// If manually flagged as an error, return invalid status
if ($this->_errorsForced) {
return false;
}
return $valid;
}
which means in a nutshell, Zend_Form will iterate over all the configured elements in the form and compare them against the values in the array you passed to it. If there is a match, it will validate that individual value against the configured validators.
So, you create form in action and then check is there post|get data. You can check is_valid form right here. You need pass $_POST or $_GET data to isValid() function. Example:
if ($request->isPost() && $form->isValid($request->getPost())) {
isValid() is function Zend_Form class. Form runs all validations for each element (just if you dont set to stop in first validation fail) and then for subforms too.
Look at Zend_Form quickstart, it's a very bright example on how to start dealing with forms in Zend.
Validating a text input looks like this:
$username = new Zend_Form_Element_Text('username');
// Passing a Zend_Validate_* object:
$username->addValidator(new Zend_Validate_Alnum());
// Passing a validator name:
$username->addValidator('alnum');
Or you can use:
$username_stringlength_validate = new Zend_Validate_StringLength(6, 20);
$username = new Zend_Form_Element_Text('username');
$username->setLabel('Username: ')
->addFilters(array('StringTrim', 'HtmlEntities'))
->setAttrib('minlength', '6')
->setAttrib('class', 'required')
->removeDecorator('label')
->removeDecorator('HtmlTag')
->removeDecorator('DtDdWrapper')
->setDecorators(array(array('ViewHelper'), array('Errors')))
->addValidator($username_stringlength_validate);