Forcing Symfony form validation without actual submission - symfony

Is it possible to perform form fields validation manually, forced?
I have a form. It has a global form validation. Everything works well if user submits data.
But I want to trigger validation before form is displayed to the user - show errors before submit.
Tried to submit using $form->submit([]) method but it doesn't trigger form fields validation.
Any ideas on this issue? Did I something wrong?

Do you need to validate a data only by form? Doesn't a validator service work for you?
Like
$violations = $this->get('validator')->validate($entity);

Reason was quite complicated and simple at once.
// form instantiation
$type = new MyType();
$options = [
'csrf_protection'=>!empty($_POST[$type->getName()])
];
$form = $this->createForm($type, [/* or entity */], $options);
$form->handleRequest($request);
if(!$form->isSubmitted()){
$form->submit([]);
}
And now I can see errors correctly. One of the most tricky part is the fact I wasn't aware Form $options are read-only after creation and empty check is mandatory if you want to leave CSRF protection turned on.

Invoke $form->isValid(); before showing the form.
However If data come from an external service, I would rather prevent (with ws validation, for example) users to submit wrong data through ws (ws = external service)

Related

What's the recommended way in Symfony of taking JSON data and populating an entity?

If I'm receiving JSON data in a request (say an API type interface), what's the Symfony recommended way of populating an entity. It seems to me the options are:
Use the form component – passing the decoded JSON as an array to the submit() method.
Use the Serializer to deserialize.
It seems to me the issue with using the serializer is that you need to manually do data transformation (and validation, though simple).
Using the form component feels kind of hacky and a also uses a lot of functionality that isn't touched/needed.
Are there other options (built into Symfony or other bundles/packages)? Or is one of these the recommended way?
(I realize this is at least partially an opinion based question...)
As you've mentioned - this is a pretty opinionated issue to deal with. The options you've been considering are the two common ways of handling it:
Just go with the Form component - need to create a FormType, adds some performance overhead (not significant in most cases). As a bonus - it gives you all the Form perks like not allowing extra fields, ability to use Form events etc.
Use Serializer + Validator - a "skinny" option in terms of components employed, a bit more verbose, doesn't come with Form perks
I'd say that there is really nothing wrong with using forms to handle deserialization and validation in one go.
Have a look at the sample action code below. Note that it is using the FOSRestBundle View class to handle responses. It simply takes in a json encoded entity data and either creates a new entity based on it or updates an existing one.
public function sampleAction(SampleEntity $sampleEntity, Request $request) {
//Is it a new or existing entity?
$statusCode = $sampleEntity->getId() ? 200 : 201;
//Load our form with the entity provided by the route loader
$form = $this->createForm(SampleEntityType::class, $sampleEntity);
//Decode the actual input and make Form component to populate an entity for us
$formData = json_decode($request->getContent(), true);
$form->submit($formData);
//Validation is as simple as this
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($sampleEntity);
$em->flush();
return View::create($form, $statusCode);
}
return View::create($form->getErrors(true, false), 400);
}

how to create save actions in api-platform

I'm trying to implement in my symfony project some api. Currently the project have many controller with standard crud, based on html table, form/validator etc.
I'm looking to the api-platform project that seam to make very easy the construction of standard rest api, and for the GET part it fit my necessities.
But for the POST/PUT/DELETE part it seam a very basic persist action on an entity, and suddenly in my project, i need to do many more actions after the persist of the entity.
I've red the docs and I'm really confused on how to do that...
I see two possibilities:
Using the event system, subscribing for the POST_WRITE for every entities
Creating a custom action for every create/update/delete actions of an entity
In both the case, I would have a really high number of single actions or event subscriber in the project (30/40), and it's really unconfortable to maintain. Also I probably have to replicate the same code that I already have in the controller, to maintain the old form system until is all rewitten in an API format.
Any suggestion on how to approach this problem?
There isn't a way to use the same controller actions, like in the FOSRestBundle, so that I can receive the data, do the various validation/persist/extra actions, and then return a result that is managed by the api-platform events?
Any way to manually call some part of the api-platform, like the deserialization/serialization, the filter and pagination from a standard controller action?
Thanks to all
Cheers
Daniele
Forgive me if I do not completely understand your question but if you already have the functionality written in the controller and you want to access the same actions via an api then maybe you can set multiple routes on each action and depending on how the action was called you can respond differently. For example:
/**
* #Route("/api/v1/tester", name="api_tester")
* #Route("/tester", name="tester")
*/
public function testerAction( Request $request )
{
$route = $request->attributes->get('_route');
if( $route == "api_tester" )
#..do things the api way
response = array( "success" => 1, "data" => $return_string );
return new Response( json_encode( $response ) );
} else { //non-api
$this->render('tester/basic.html.twig', array();
}
}
You can evaluate which route was used and in various sections of your actions you can handle things differently based on if the action was called via the api or from a normal request.

Which is the suggested place to modify binded form data in Symfony?

I've a form for creating a new Customer. A customer may have a mobile number. Mobile number should be persisted without + or 00 prefix that user can type. This can be accomplished easly with:
$customer->setMobile(preg_replace("/^(\+|00)/", '', $customer->getMobile()));
Which is the best place to put this code?
Inside a CustomerController prior to call entity manager and persist the entity. Is this really a matter of a controller in MVC pattern?
Using a SanitizeCustomerSubscriber and listening to FormEvents:POST_BIND event
Using a CustomerSanitizer service
Any other idea? Of course i'm speaking of data manipulation in general, mobile number is just an example: fields to be sanitized could be more than just one.
You should do this in the PRE_BIND event, where you can access the submitted data before it is being processed.
$builder->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) {
$data = $event->getData();
if (isset($data['mobile'])) {
$data['mobile'] = preg_replace("/^(\+|00)/", '', $data['mobile']);
}
$event->setData($data);
});
For the record, as of Symfony 2.3, this event is called PRE_SUBMIT.
I'd put this into the Customer setMobile() method — the closer to the data itself, the better. This way the mobile number will be sanitized no matter what controllers or forms are used to set it.

login without form submit

I was looking and looking a bit too long time for a solution for my problem and I can hardly find anything focused on the topic which bothers me.
Namely: Do you have any idea if user login can be processed inside symfony2 without using a form login? To be more precise, I mean let's say something like this:
$this->authenticationManager->login($user->getUsername(), $user->getPassword());
For now I have two ideas to do what I want to do but a bit differently:
Take advantage of AJAX and send arequest via POST to loginAction with it (unfortunately this is not going to work if JavaScript would have been disabled)
In symfony's docs I found an option post_only: true which when I set to false lets me access loginAction wih GET method so simple redirect would have done the job here.
nevertheless I would prefer the solution I'm searching for.
BTW: Can you tell me how to generate csrf token if I needed it to successfully submit login data?
You can manually set the authentification token:
// Inside an action, for example. You already need an user.
$providerKey = 'main'; // your firewall name
$token = new UsernamePasswordToken($user, null, $providerKey, $user->getRoles());
$this->container->get('security.context')->setToken($token);
Found here.

How to update the value of a single field invoking appropriate validation

I'm making a module to allow users to update single fields on in this case, their user entity.
The code below is an example of the method I have initially been using to get it working and test other elements of the module
global $user;
$account = user_load($user->uid);
$edit = (array) $account;
$edit['field_lastname']['und'][0]['value'] = 'test';
user_save($account, $edit);
However this bypasses any field validation defined elsewhere in Drupal. I don't want to reproduce any validation written elsewhere - it's not the Drupal way!
My question is: Is there a function in Drupal 7 that can be called to update the value of a single field. I imagine such a function would clear the appropriate caches, invoke the fields validation etc.
I am aware the solution will be totally different to my current user object based one. I just can't for the life of me find the appropriate function in the API. I wander whether the fact I am looking for a save function alone is the problem - and that there are some other necessary steps that come before.
Any help gratefully appreciated.
Check out the drupal_form_submit function. It lets you submit forms from code. In this case, you could use it to the user edit form, which would then fire the appropriate validation.

Resources