I'm trying to use symfony2 to create a web service. I'd like the webservice to be structured and listen for:
POST to /teams/list with params key1=value and key2=value2
For validation purposes, i've created a TeamForm object and a TeamFormModel to validate the data against (using annotations). The problem i'm having is that the form is looking for team[key1] and team[key2] instead of just key1 and key2 to bind to the TeamFormModel.
Is there a way to configure the form to not use the team[*]?
If you are using the 2.1 branch, it's easy you can simply create a form with an empty name.
$form = $this->get('form.factory')->createNamed(
'', // the name
new TeamType(), // the type
$team // the data
);
$form->bindRequest($request);
So it will work as you are expecting.
But if you are using the 2.0 branch, from what I know, it's not supported and you have to do the binding manually:
$form = $this->createForm(new TeamType(), $team);
$from->bind($request->request->all());
You can validate entity without creating form. You can create entity object from POST data and pass it to validator. See validation section of the cookbook.
If you don't like to create entity object from request parameters every time then you can post data in json or xml format and then de-serialize into entity object using JMSSerializerBundle.
Related
I'm trying to validate submitted data against existing Model/Entity/POPO, however I can't get it to work in any simple way.
All of this is takes place inside a controller action.
So, I can do like this:
$constraints = new Assert\Collection([
'username' => [new Assert\NotBlank()],
'email' => [new Assert\Email()],
]);
$violationList = $this->get('validator')->validate($request->request->all(), $constraints);
However to do that in every action makes no sense, as having all constraints in a class would be a lot better. So, Validation component allows to do like this:
// All constraints are defined inside Customer class
$customer = new Customer();
$violationList = $this->get('validator')->validate($customer);
Violation list is full of errors now, as $customer is an empty object, but the problem is I can't find a way to use data from POST AND validate it against constraints that are defined in the class.
It is possible to write extra component/helper that would take POST data and then will call bunch of ->setUsername(), ->setEmail(), etc., but that doesn't seem right considering you can easily map Model to POST data, if:
Form component is involved;
OR using ConstraintsCollection manually;
Am I missing something obvious here or there is no out-of-the-box possibility? Thanks!
AFAIK the form component is the one responsible for mapping post data to your entity. So you have two choices
Use a form, like that you will have your data mapped and your model validated
Skip the form but then you have to map request params to your entity manually. then validate your model with $this->get('validator')->validate($customer);
Edit :
The form role is to map data coming from request ( html form , api .... ) to a model. Validation could be done with from or without it as its the validator component who does the job , it should be noted that the validation is done on the model and not the form.
If you want to skip the form check this question: Populate entity from data array without form/request although the form component is very useful specially if you are using the same logic in many places ( create / edit .. )
I'm implementing patch method using fosrestbundle and I want to create proper patch method.
To do so I've created controler and there is patchAction which takes an argument Entity, Entity is created passed via ParamConverter which I wrote myself. The Entity is passed to EntityType and here's the problem. I want to update only fields that changed and when I pass Entity to form it set nulls to object that comes from request. Entity is POPO
Here's the flow
User sends PATCH request to /entity/{Entity} let's say /entity/12
Param converter converts 12 to proper Entity asking DB for the data
EntityFormType takes Entity as argument and sets data from request to entity.
Entity is stored to DB
The problem is that form after it takes whole Entity object it sets null for fields that are null on form. I'd prefer if it took these values and set it for example as defaults.
I don't and can't use doctrine ORM.
The code:
/**
* #ParamConverter("Entity", class="Entity")
*/
public function patchAction(Entity $entity, Request $request)
{
var_dump($entity); // object mapped from DB
$form = $this->createForm(new EntityType(), $entity);
$form->handleRequest($request);
$form->submit($request);
var_dump($entity);exit; //here I get only values that i passed through patch method, rest of them is set to null
}
I was thinking about form events or creating something like diff method but probably there is better solution?
You need to create your form with method option set.
$form = $this->createForm(new EntityType(), $entity, array(
'method' => $request->getMethod(),
));
If request is send with PATH method then Symfony will update only sent fields.
How to fake PATCH method in Symfony: http://symfony.com/doc/current/cookbook/routing/method_parameters.html#faking-the-method-with-method
I an using the symfony form to create a form and validate it. But i want to pre-validate the form on page loading itself ie. validate the form without post. Is it possible to do it in symfony?.
I have tried to use $form1->isValid(); on the else part of post. But its not working.
Also I tried to use the submit(),
$data = $form1->getData();
$form1->submit($data);
$form1->isValid();
but with no success
*the form fields are dynamic and the validations are also dynamic. So a form that is preloaded can have error fields.
What you can do is for sure manual Entity Validation. I can imagine cases when you can't trust data already saved in database or, you want to pre-fill object with data from other source (external request response) before giving it for user to edit.
Please read docs about validation here: http://symfony.com/doc/current/book/validation.html
Possible code:
$author = new Author();
// ... do something to the $author object
$validator = $this->get('validator');
$errors = $validator->validate($author);
In this case you don't use constraints from FormType but validator constraints (they can be declared in entity - they will be used also by FormType): http://symfony.com/doc/current/book/validation.html#constraints
Let say I have an HTML form with bunch of fields. Some fields belong to Product, some to Order, some to Other. When the form is submitted I want to take that request and then create Symfony forms for Product, Order, and Other in controller. Then I want to take partial form data and bind it with appropriate forms. An example would something like this:
$productArray = array('name'=>$request->get('name'));
$pf = $this->createForm(new \MyBundle\Form\ProductType(), $product);
$pf->bind($productArray);
if($pf->isValid()) {
// submit product data
}
// Do same for Order (but use order data)
// Do same for Other (but use other data)
The thing is when I try to do it, I can't get $form->isValid() method working. It seems that bind() step fails. I have a suspicion that it might have to do with the form token, but I not sure how to fix it. Again, I build my own HTML form in a view (I did not use form_widget(), cause of all complications it would require to merge bunch of FormTypes into one somehow). I just want a very simple way to use basic HTML form together with Symfony form feature set.
Can anyone tell me is this even possible with Symfony and how do I go about doing it?
You need to disable CSRF token to manually bind data.
To do this you can pass the csrf_protection option when creating form object.
Like this:
$pf = $this->createForm(new \MyBundle\Form\ProductType(), $product, array(
'csrf_protection' => false
));
I feel like you might need a form that embed the other forms:
// Main form
$builder
->add('product', new ProductType)
->add('order', new OrderType);
and have an object that contains association to these other objects to which you bind to the request. Like so you just have to bind one object with the request and access embedded object via simple getters.
Am I clear enough?
I use this code
$builder->add('userTasks','collection',array('type' => new UserTaskType()));
This is working fine
userTasks will be a collection different userTask objects which will in turn create the form.
Now is there any way that i can pass that individual UserTask object in the constructor like this
$builder->add('userTasks','collection',array('type' => new UserTaskType($userTask)));
so that i can use that to generate Label for the form.
Is it possible
If i use $user->UseTasks then that will be a collection of all tasks but i only want that object whose form is being created
If I understand the question correctly, you want to adjust the form based on the actual data object which the form will be bound to? It is one of the those simple sounding requirements that is actually a bit involved.
You need to use the form event system:
http://symfony.com/doc/master/cookbook/form/dynamic_form_generation.html
It's not so bad once you have worked through it.
===
To answer the first comment:
public function preSetData(DataEvent $event)
{
$data = $event->getData();
$form = $event->getForm();
$data will be your object, in this case a $userTask.