I am submitting a form with a lot of fields and trying to validate it with handleRequest($request) as it is shown in the Symfony documentation.
My entity is very big and has a lot of relations with other entities.
handleRequest($request) is validating each form field submitted and checking for errors.
The problem found is while submitting an id of a related entity of my main entity (in example a person of an office), handleRequest will internally get all objects of the related entity (the full table of the related entity, all persons) and hydrating them as objects.
I think it should just check if the submitted id exists in the other table, get that related entity object and check it for errors (instead of getting all the related table).
If you check and debug the source code of Symfony2 handleRequest, you may easily spot the same problem at this lines:
Form/Form.php
// Normalize data to unified representation
$normData = $this->viewToNorm($viewData);
$value = $transformers[$i]->reverseTransform($value);
How can I still validate the form without dealing with this issue which makes it insanely slow to validate a form with handleRequest($request)?
If I don't use handleRequest to validate it, which automatically add the errors to my form for each field, how could I manually validate each field and later add the errors to my form for each field and show them in the next view?
This question is a little vague, and the answer very much depends on your specific form. Please post the form definition that is giving you the hardest time.
Check to make sure that you are not EAGER fetching associations here.
handleRequest() is going to take the request object and construct the model that your form describes, as your form defined it to.
If the objects are required in order to display data on your initial form to the user, or to validate the data on submit, the "entity" field type will fetch all of the objects you told it to in its definition. If you are displaying a big select list, for example, all of this data is needed.
I had a similar problem in the past and it was because I was using a lot of choice fields that were being used as a series of multiple select checkboxes. My bottleneck was actually in the twig layer while rendering out the thousands of checkboxes I had stored as separate entities.
I switched from a set of checkboxes to a single multi-select box and it increased my speed significantly.
in my case, after having a similar behaviour I detected that it was a problem in my xdebug configuration. By editing php.ini and disabling xdebug I found that everything went much faster. It can be interesting to do this check when all else fails. I'm leaving this message here in case it might be of help to someone else.
Related
The Symfony 2 Form Component really is something. I guess you know that. Trying to understand what works how is just an seemingly impossible task; and I'm quite experienced at browsing through codebases.. But man, the Form component.. OMG
TL;DR
Below are details, this issue tries to ask
Is it possible to replace the class \Symfony\Component\Form\Form?
Or: How to easily get all extra data from all fields of type form of a form?
Or, a related question: How on earth does it work that if i do $form->add('ss', 'form') - obviously the Core\FormType class gets involved but when i retrieve it later, it is an instance of \Symfony\Component\Form\Form? Where does that happen and can this maybe overriden so it uses a different class there?
Details
The situation
Imagine a Controller that receives a n deep JSON payload. This payload gets decoded and validated through Form. Now, most of this JSON structure is mapped by Models (Doctrine ODM Entities). But some sub-properties are just "hashes" - the client is allowed to post whatever he wants there.
Those "hash" subproperties are fields of type form, are compound flagged and can have extra fields.
The problem
Bottom line our problem is, that all "extra fields" are not returned by $form->getData(). We are unable to specify those fields (and their types) as we don't know what will come - so all this data is part of extraData.
The solution?
So i thought - OK - let's modify the FormFactory so it'll return our Custom extension of Form - one that also returns extraData when getData is called. Easy right.? Noo, not easy..
My idea let me inspect FormFactory, the FormBuilders, the ResolvedFormTypes, whatnot.. and at all important places (like formBuilder->getForm()) - the classes I want to override/replace are instanciated static - no usage of the DIC..(!)
I've read somewhere that the Form component in Symfony 2 was written by the devil himself to let we developer go mad. Luckily I'm not so mad to try to replace the entire Form component by myself ;)
Jokes aside, when you define a form (by creating a <entity>Type class, like UserType) you are defining a new type that can be as simple as a single text input or as complex as full-fledged form (our UserType from before). The "real" form (Symfony\Component\Form\Form) is created from your type definition:
return $this->container->get('form.factory')->create(
new UserType(), new User(), $options
);
Have you evaluated the idea to create a custom form type for your "extraData"? Or maybe it can be mapped as a JSON string that's created by a client-side JavaScript before submit.
I'm using Symfony Form standalone (i.e. not the full stack framework) to build an "images" type that allows users to upload 1-x images and give each one a title, change the order of the uploaded images and so on.
I've done this by creating an images type which contains a file and a text field. I've also subclassed the CollectionType to act as a holder (like in the cookbook example). Lastly, I have a dedicated storage class associated with the CollectionType which takes care of persisting the uploaded data (I can't persist the individual images separately since I also need to save the order).
This all works more or less, i.e. I can add/update/delete images normally. The only problem I have is when there is a validation error in some other field in the same form (e.g. if I don't fill out a required field). In this situation, the uploaded file never reaches the storage class, and when the form is rendered again, the view data is in the wrong format. So I've added a ViewTransformer to my custom CollectionType that detects this case and performs the necessary transformation. Which basically works, but unfortunately, it puts the transformed data into the wrong place: The FormView instance corresponding to the CollectionType has the correct (i.e. transformed) data, while the child instance (i.e. the image type) has the untransformed values. So the question is: Can I make it pass the transformed data to the correct child, or shouldn't this happen automatically even?
I can provide some example code if it helps, but it might take a moment to extract only the relevant parts. In the meantime I wanted to ask: Am I even approaching this problem in the right way? The documentation on the inner workings of Symfony Form is a bit wanting, so I'm not sure if there wouldn't be an easier way to do what I am trying to do.
EDIT: After a lot of debugging I found out that my problem is that Transformers are called differently during submit() and setData(): During submit() (i.e. when data is loaded from the storage backend), the view transformer runs on the parent (i.e. CollectionType), and afterwards the converted $viewData is passed to the children. During submit(), it's the other way around: First, the child data is mapped, and afterwards the view transformer is run. I think I'll open a ticket on gh...
In Symfony 2.5.10, I have multiple form types, each with their own validation groups, calling various class constraints. Each type represents a particular step in a workflow. The final step iterates over all other steps, performs the necessary validation and displays any possible violations to the user.
The data behind each form type (data_class) is always the same: a doctrine entity.
Each displayed violation links to the URL/path representing the step in question, with an additional parameter which, when present, should trigger the validation. The idea is that the form should display the errors immediately, without submitting. In other words, I wish to trigger form submission programmatically (server-side, not JS!).
I've tried various different ways:
Somehow put the entity (which I have) into the request and set the method of the latter to POST, so that Form::handleRequest handles everything automatically. Problem: converting the entity object to an array, as would be returned from a real form submission. Maybe a DataTransformer? PropertyAccessor?
As 1. but call Form::submit instead. See http://symfony.com/doc/2.5/cookbook/form/direct_submit.html#calling-form-submit-manually
Validate myself (in the same way I do in the final step), giving me a ConstraintViolationList. Iterate over the list and call Form::addError for each violation. Problem: I need to add the errors to the correct child elements, not just the parent. Maybe I could do this using the propertyPath of each error, but how to go from that to child form?
Any help would be much appreciated. I've trawled stackoverflow and the web in general, but to no avail.
First way looks good. You just should check the ajax form and them just use something like
$entity = $form->getData()
to retrieve data from form (which could be array, entity, or some other stuff you have in you form).
Then just pass this entity to the twig view to form an request answer. Alongside with entity you might want to provide form errors aquired from $form->createView() FormView object.
A very interesting subject has arisen today with two points of view.
Using Doctrine Entities
Should the validation of the data be done at the point when a setter method is called? I.e. Inside a setFieldName() method, or
Should the entity be validated as a whole for valid data when an event is triggered on an entity?
Is there a normal or tried and tested theory and/or point of view on this?
I don't think there is a "normal"/standard way to go about this - I guess it depends on your needs. I can tell you my point of view:
For me data validation should be done on setters - that is - as soon as possible. This way you cannot have an entity with invalid data set on it and it will save you headaches when you are going to persist.
Try to think of it this way: Let's say you have a car that runs on petrol. You go to the gas station to refill. You have two pumps: petrol and gasoline. Without validation, you would be able to put either type of fuel in there and until you turn the engine on nothing would happen. But when you do, if you put the wrong type of fuel, it would be too late. Boooooooom! Of course entities don't explode.;)
Having said that, sometimes it is not possible to do validation on a single setter because it could be dependent on another property(which has not been yet set). Something like VATID for user entity where property user_type(private|company) has to be available in order to be able to check and force VATID for companies. In this case you'd do some PrePersist/PreUpdate validation.
I'm working on my first CodeIgniter application and have encountered some confusion around handling post data.
More specifically, I understand the role of $this->form_validation->set_rules(), and how set_value() works to repopulate input values when the validation failed, but what I can't figure out is if $this->input->post is the same value as the set_value equivalent.
I understand that the majority of validation rules would have a boolean result, however what about ones like trim|htmlspecialchars - these also have the benefit of preparing the data for db queries.
So in my model, can I access the inputs after being processed by the Form Validation library, or should I do the additional preparation inside the model directly onto $this->input->post('variable')?
My gut tells me that I should add final processing like htmlspecialchars right before the SQL in the model, as it is really a db specific operation (I would not want & instead of & in my form inputs, but I would want & in the database).
Incidentally in my reading I did come across $this->validation->variable which would appear to have been the answer to my question in previous CI versions.
They are similar, but not exactly the same.
You would use $this->input->post('variable'); within the controller only. This variable will be validated and cleaned (if you decide to clean it with xss_clean or apply any other prepping functions).
set_value() should only be used within the Views. While this is not essential, the real value of doing this opposed to using $this->input->post is you can set a "default" value as the 2nd parameter which is automatically used if the post value is empty.
As mentioned set_value() is strictly for repopulating form inputs - nothing else. For example, set_checkbox() is going to return something like checked="checked" which is obviously not what you want to send to your model.
There's room for argument about where the input validation and prepping should be handled, but most will agree that it should be done in the controller.
You can do additional processing in the model if you wish, but generally you don't want to be accessing $_POST from the model - it makes the model less useful. Not all data is going to be coming straight from the user, so it's better to prep the data beforehand and send it as a new array/object to the model. The model should not care where the data is coming from.
Let the form validation library and controller layer process the user input (what it's intended for), and the model can process the data you send to it.
Developer
I work both frame work cakephp and codeignator. I feel best thing cakephp data validation. spouse you have 8 fields form you create validation in controller with designator. After validation all fields is empty if you fill 8 fields and by mistake 1 fields miss then after validation codeignator data validation refresh page and empty all fields.
but in cake php just opposite data validation create in model you create one time validation and use some thins when you call model then call validation exp: add,edit.