I have a complicated form which has lots of fields in it and it was created by an other developer. Now when I submit the form I get the very common error
This value should not be blank.
I need to find out what is the value. I know about Entities mapping and "nullable=false" property, what I actually need is, the best practice/technique or just a solution, to find out what is this value that is missing. It is a complicated Form and if there is a different path to take rather than go through entity and all subfields that are added to it, I would really appreciate it.
I am pretty sure Symfony devs would have considered that and I need to find how to solve this?
If you are doing this for debugging purpose, you could do something like:
{{ dump(form.getErrors(TRUE,TRUE)) }}
As for the production, you need to put appropriate validation constraint's messages. For example, using annotaions:
use Symfony\Component\Validator\Constraints\NotBlank;
/**
* #NotBlank(message="Title should not be empty")
*/
private $title;
After that, error should display the message above instead of generic one.
There may be new NotBlank() attached to form field in formtype
class.
There may be #Assert\NotBlank attached to field property in entity
class.
There may be #Assert\NotBlank attached to field property in model
class.
So if you set update them as below, you'll know what field it is.
new NotBlank('message' => 'Code is required.')
#Assert\NotBlank(message="Code is required.")
Or just work with Form error handling class.
Related
Im creating an edit page for my model where I have the following code:
<f:form action="createEditSave" addQueryString="1" method="POST" object="{activity}" objectName="activity">
<f:form.select property="competence" options="{competences}" prependOptionLabel="" prependOptionValue="" optionLabelField="name" />
</f:form>
When I submit the form(and select an option in the select) I expect the model in my createEditSaveAction to contain in this case a competence. But it remains empty even though the request does contain the argument. Am I wrong in thinking it should automatically select the object and must I handle it myself in my createEditSaveAction?
I believe my html is correct.
When submitting my form I receive no validation errors and get correctly send to my createEditSaveAction. Only here I expect my Activity model to have a competence model but the setCompetence() function receives a empty objectStorage.
Depends on what happened to send you back to the form:
If the problem was validation errors the value should be prefilled since it will exist in the request data from the referring request, which is then read by the ViewHelper to determine the current value.
If you redirected to an edit action the property value only exists on the object you passed and if that object is, for example, not assigned as a template variable in the action that displays your form.
It may help if you specify the optionValueField property - and it may also help if you explicitly pass a value for the field.
Don't forget that if your use case is somehow too specialised to fit this, you can always use f:form.select.option in a loop to render options manually, including selected attribute.
Final word: from the naming of your action it looks like you have one action that is capable of both creating and updating an object. This is bad practice - you should be using two different actions for this, and on the "new" action your object argument should be optional and null by default, on "edit" it should be mandatory. It may also be a good opportunity to review your controller in general, to confirm that it actually does use properly declared and annotated arguments and argument types for all the actions. If you circumvent the framework, things like form validation and subsequently resolving of field values may not work like you expect.
Resolved my own issue. The problem was the annotation in my model which said it was a objectStorage.
Had a similar issue with my form, I had to include both the name and the propery tag.
<f:form.select name="foo" property="foo">
<f:form.select.option value="bar">Bar</f:form.select.option>
</f:form.select>
I want to create readonly hidden field. Now I have field that looks like this:
$builder
->add('question_category_id', HiddenType::class);
And entity has method:
public function getQuestionCategoryId() {
return $this->getQuestion()->getQuestionCategory()->getId();
}
After saving I got following error:
Neither the property "question_category_id" nor one of the methods "addQuestionCategoryId()"/"removeQuestionCategoryId()", "setQuestionCategoryId()", "questionCategoryId()", "__set()" or "__call()" exist and have public access in class "Entity\UnitQuestionAnswer".
I could add dummy method
public function setQuestionCategoryId($id) {
return $this;
}
but it is not right way.
How to create readonly hidden field, or avoid of writing back data from from into entity?
S2.8 has a read_only attribute which would do what you want but it has been removed in 3.0.
The disabled attribute should work. Just be aware that the value itself will not actually be submitted symfony.com/doc/current/reference/forms/types/… so if you are doing anything funky with the posted data then that could be a problem.
I suppose it's possible to fool around with the internals but that would be more trouble than it is worth.
Personally, given that my get method was added just for the form, I would just add a corresponding set method and move on.
I use a certain form in several places. In one of them I need to ignore a form element which I set programmatically after the validation.
Because it's just an exception I don't want to create a new form. So I thought, I just remove this element in the controller like:
$myForm->remove('myElement');
The problem is that the form now won't validate. I don't get any errors but the $myForm->isValid() just returns an empty value.
Any ideas what I might be doing wrong?
Ok, finally I found a solution! You can define a ValidationGroup which allows you to set the attributes you'd like to validate. The others are not validated:
$form->setValidationGroup('name', 'email', 'subject', 'message');
$form->setData($data);
if ($form->isValid()) {
...
The first thing I thought about was to remove the validator from your myElement's ValidatorChain. You could get it within the controller with:
$form->getInputFilter()->get( 'myElement' )->getValidatorChain()
It seems like you can't remove from the ValidatorChain, just add. Check this post. Matthew Weier O'Phinney, from Zend, explains why it can't be done and a possible solution for your scenario.
The way I solve this problem, is checking the 'remove condition' when I create the validator in the FormFilter class. If you use annotations I think it doesn't works for you, so Matthew suggestions is the one you should use.
Or you could try the one in this post from #Stoyan Dimov: define two forms, a kind of BasicForm and ExtendedForm. The first one have all the common form elements, the second one is an extended one of the other with the rest of fields. Depending on your condition you could use one or another.
In class ValidatorChain implements Countable, ValidatorInterface, add a new method:
public function remove($name){
foreach ($this->validators as $key => $element) {
$validator = $element['instance'];
if($validator instanceof $name){
unset($this->validators[$key]);
break;
}
}
}
Use like this:
$form->getInputFilter()->get("xxxxx")->getValidatorChain()->remove('xxxxxx');
There must be a validator defined for this particular element that you are trying to remove.
In your controller where you are adding new elements to form, there must be addValidator calling like:
$element->addValidator('alnum');
That is actually causing validation to be failed. So you have removed the element from form but you still have validation defined on that element to be checked.
If you are not able to find this validation adding function in controller, try to see if it has been defined through config file.
You can read further about form validation in zf here: http://framework.zend.com/manual/1.12/en/zend.form.elements.html
I remove the element with:
$form->get('product')->remove('version');
When I post the form I disable the validator on this element with :
$form->getInputFilter()->get('product')->get('version')->setRequired(FALSE);
Due to my project requirements, I must add a numeric code to each and every constraint violation, additional to the message. I have looked through the ConstraintViolation class and seen that it does indeed implement a $code property, so that would be perfect for my needs... except there is no easy way that I could find to specify this code on the annotations.
For instance, looking at how either the Email constraint or its parent class are implemented, there's no sign of that code anywhere, which makes it impossible for the annotations to define it.
The validators also inhibit the coder from setting the $code, as they don't pass the fifth parameter to addValidation, which is the code itself.
$this->context->addViolation($constraint->message, array('{{ value }}' => $value));
So, my question is simple: am I missing something? Is there a way to set the constraint violation code via annotations that is not a pain? Ideally, I would like to do something like that:
/**
* #Assert\NotBlank(code=400)
* #Assert\Email(code=401)
*/
protected $email;
Editing Constraint.php to add the $code property (for being a valid annotation code) and all the constraint validators to pass the fifth parameter to addviolation seems a terrible idea!
Of course I could implement my very own validators, but what is the point on having a set of predefined validators then? It's just a one-line change.
I think you have a slight mistake. The code property in the validator is not the one you should look at. I think you should just create your own Validator constraints which are very simple classes:
https://github.com/symfony/Validator/blob/master/Constraints/Choice.php
And just toss in a public code property which then you can set via annotation or PHP. You dont need a new validation service, just that extra property. This propery will be added automatically when the constraint is constructed:
https://github.com/symfony/Validator/blob/master/Constraint.php
Here is more info on how to create the custom constraint:
http://symfony.com/doc/2.1/cookbook/validation/custom_constraint.html
I have some complex validation going on with my symfony form, and I need to be able to assign an error to a specific field from my controller. Right now, I have global errors working like this:
$error = new formerror("There is an error with the form");
$form->addError($error);
But that creates a global error, not one bound to a specific field.
Is there a way to throw an error on a specific field from my controller?
Thanks to some help over IRC (thanks #fkrauthan!) I came up with an answer.
Every field in SF2 is actually an instance of form. What you need to do is access the form object of the field, and add then error onto it. Thankfully, symfony provides a method to get an embedded form/field.
Heres my code:
$error = new FormError("There is an error with the field");
$form->get('field')->addError($error);
As some people have pointed out, you will need to include the FormError class at the top of your file:
use Symfony\Component\Form\FormError;