Empty values for POSTed null select option values
- helvete
- Member | 16
Hello!
I have a form, where users are about to select value from select box. The
select box reflects database foreign key column, which allows nulls. Let's call
it hobby_id
.
Now when I generate the form, All hobbies are added as available option plus
one extra option of value null
and text 'N/A'
is also
added. Obviously the user can have no hobbies.
The post value for the empty option is empty and evaluated to ''
when processing form values via $form->getValues()
. And here
comes the problem. The database column is of type INT
while
allowing null
value, but the empty string (''
) gets
autoretyped to 0 which bothers me.
I know I can traverse the values array and retype the FK empty string
values into null
s, but obviously I don't like this solution.
I have tried to add a condition to the select control to check if it is
filled and added filter to return null
in case of ''
,
but the default validation comes in and evaluates the select as invalid even
before the filter is applied.
Is there some sane solution how to configure the select element to behave like this?
Thanks for any insights in advance.
Edit:
I have read these, but nothing hints any nice solution:
https://forum.nette.org/…zdne-hodnoty
https://forum.nette.org/…na-condition
https://github.com/…/issues/1088
https://forum.nette.org/…ce-formularu
..and many more
Last edited by helvete (2015-11-06 11:35)
- greeny
- Member | 405
I assume you have validation similar to this:
$form->addSelect(...)
->addRule($form::INTEGER); // or $form::FLOAT
You can then change it to this:
$form->addSelect(...)
->addCondition($form::FILLED) // rules applies only if the field is filled, e.g. not empty string
->addRule($form::INTEGER);
Then validation vill accept empty string and you will have empty string in application's code.
And in your form's success handler just do something like this:
public function formSuccess($form, $values)
{
if ($values->hobby_id === '') {
$values->hobby_id = NULL;
}
$this->userRepo->persist($values); // replace with your saving code
}
- greeny
- Member | 405
This situation is common, but in most big projects, you are not using Nette/Database, but Doctrine. In Doctrine, you add mapping to Entity, so foreign keys are not used, instead you access entities directly. So your code would look like this:
public function formSuccess($form, $values)
{
$this->user->setHobby($this->hobbyRepo->find($values->hobby_id)); // obviously, there is no Hobby with id = '', so NULL is returned
$this->em->persist($user);
}
Thats why not much users are actually solving issues like this.
- helvete
- Member | 16
Yeah, I am quite experienced with doctrine, but we switched of off it (Zend+Doctrin) in favour of Nette+NetteDatabase because of Doctrine's enormous resources usage inefficiency and because of currently increasing amount of smaller projects we work on.
I will implement similar solution as you suggest on the parent-most level model class.
Edit: In the end solved by adding lines like this into model insert and update methods.
// strip empty FK column field values
foreach ($values as $key => $value) {
if (!preg_match('/_id$/', $key)) {
continue;
}
if ($value === '') {
unset($values[$key]);
}
}
Thanks for insight.
Last edited by helvete (2015-11-06 13:08)