Symfony2 - How to preserve request parameter when submitting form? - php

Here's the situation : Some form handling action is invoked from twig template with request POST parameter (ie. entity ID). After the form is submitted and action is being invoked once again to modify value of the underlying object, my entity ID parameter from Request object is gone (it's replaced by Symfony Form request object).
Here's the question : What's the best practice to preserve this request parameter between two invokes of the form?
Here's simple code example :
public function editEntityAction(Request $request, $type)
{
$objId = $request->request->get('entityId');
$updateObj = null;
$form = null;
$dbMen = $dbMen->getRepository('BakaMainBundle:Brand');
$updateObj = $dbMen->find($objId);
$form = $this->createForm(new AddBrand(), $updateObj);
if ($updateObj == null && $form == null)
$this->redirectToRoute('baka_main_main_index');
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted())
{
$menager = $this->getDoctrine()->getManager();
$menager->flush();
}
return $this->render('#BakaMain/Specs/EditEntity.html.twig',
array('form' => ($form->createView()));
}

There are three possible ways to preserve values
sessions
cookies
hidden form fields
you could store it in parameters.yml only if its a global configuration variable that is used across the application
there are flashbags used to display flash messages such as 'success form submitted' or 'form submission failed' which is valid exactly once for the next request
i've given you all the options, you can choose accordingly, you can ask me additional details if needed

Related

Drupal 8 Form with custom action

I have created a ModalDialog in Drupal contain two forms like as follows,
public function signUpForm() {
$response = new AjaxResponse();
// Get the modal form using the form builder.
$modal_form[] = $this->formBuilder->getForm('Drupal\signup_form\Form\SignupForm');
$modal_form[] = $this->formBuilder->getForm('Drupal\signup_form\Form\SigninForm');
// Add an AJAX command to open a modal dialog with the form as the content.
$response->addCommand(new OpenModalDialogCommand('', $modal_form, ['width' => '800','dialogClass' => 'signup-modal']));
return $response;
}
The forms are rendered, But the problem is ,both forms are submitting to the same function. I am unable to change the action of the form.
Is there any options available to change the form action to a custom url?
You need to alter these forms so that you can add your own submit handlers (and remove the unwanted one), and eventually from there you will be able to set the appropriate redirect, or AjaxResponse.
For example, for each form, implement hook_form_alter from a custom module :
function MODULE_signup_form_alter(&$form, FormStateInterface $form_state, $form_id) {
$form['actions']['submit']['#attributes']['class'][] = 'use-ajax-submit';
$form['actions']['submit']['#submit'][] = 'MODULE_signup_form_ajax_submit';
}
Then add the appropriate submit handlers, eg. :
function MODULE_signup_form_ajax_submit(array $form, FormStateInterface &$form_state) {
$response = new AjaxResponse();
$form-class = '.signup-form'; # using your own selector
$selector = '#drupal-modal' . ' ' . $form-class;
$message = '<div>submitted</div>';
$response->addCommand(new ReplaceCommand($selector, $message));
$form_state->setResponse($response);
}
I assumed you want to update the modal content so that the second form can still be submitted, so here I added the 'use-ajax-submit' class (cf. Drupal.behaviors.AJAX) to the appropriate $form action attributes so that the submit response can be rendered in the modal as well. Also used the ReplaceCommand to replace the submitted form content with a simple message.
If instead the first submitted form should trigger a redirection, then don't use setResponse() (that actually cancels redirect), and use setRedirect() if the base action url is not the one that you want.

Symfony validate entity using form

$userData = (new User())
->setPersonCode(123)
->setPhone('+470002342342342');
$userForm = $this->toolbar->getForm(UserType::class, $userData);
I'm creating form from entity class where is setted data. If now I try use:
$userForm->isValid();
I'm getting true, because form data is not submitted, how I can do validation, without setting manually data to form and submitting ?
If you don't want to submit data to a form, skip forms entirely; use the Validator service directly:
<?php
// (Assuming you're in a controller, otherwise inject the validator some other way.)
$userData = (new User())
->setPersonCode(123)
->setPhone('+470002342342342');
$validator = $this->get('validator');
$errors = $validator->validate($userData);
$isValid = count($errors) === 0;
Your question is worded a little strange and im not sure exactly what you want, If you want to manually set the data like above then call $form->submit() passing the user data.
$userData = (new User())
->setPersonCode(123)
->setPhone('+470002342342342');
$userForm = $this->toolbar->getForm(UserType::class);
$userForm->submit($userData);
if(!$userForm->isValid()){
// handle errors
}
If you want to have the user submit data on a form then do something like this:
public function createUserAction(Request $request)
{
$userForm = $this->toolbar->getForm(UserType::class);
$userForm->handleRequest();
if(!$userForm->isValid()){
// handle errors
}
}
$userForm->handleRequest(); will handle taking data that was submitted from the form on the page.

Symfony2 decode and compare pass

I need to make a form:
when I choose user from list I will get an input where user will be able to write password (for selected user).
And I must compare if the password agrees with the pass from database.
I found one solution on stack. But I asking if meaby there is other way to make it?
Any ideas?
here is what I already done:
Controller:
public function UserAction(Request $request){
$form = $this->createForm(new UserIncType());
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()){
$valuePass=$form->get('Password')->getData();
$valueUser=$form->get('User')->getData();
$security_encoder = null;
$userRepo= $this->getDoctrine()->getRepository('MainCoreBundle:User');
$user = $userRepo->findById($valueUser);
$security_encoder = $this->get('security.encoder_factory')->getEncoder($user);
$password = $request->get('password');
}
return $this->redirect($this->generateUrl('permits_show'));
}
How to decode pass from database and comapre it with pass from form?
Or is there any other way to make it?

kohana 3 creating routes with get

This has to do with routing. So for getting parameters via url, you basically pass the data to the url following the route format you set.
This is working with links. I created the route, passed the data into the url, and used the request method to get the parameter for use in the controller. like URL::site("site/$color/$size")
What if I am constructing the url by form submission? For example, if I want to create a basic search query.
How do I get my form submission to look like this search/orange/large and not like this search.php?color=orange&size=large when I submit a form via get method.
By definition, the GET method puts the submitted information as URL parameters. If you specifically want to end up with a URL like site/$color/$size, you can use the POST-REDIRECT-GET pattern.
A partial example, from a controller on one of my sites (there is a submit button on the page named clear_cache_button):
public function action_index()
{
$session = Session::instance();
$is_post = (Request::current()->post('submit_button') !== NULL);
$is_clear_cache = (Request::current()->post('clear_cache_button') !== NULL);
$p = Database::instance()->table_prefix();
$people = DB::query(Database::SELECT, "
SELECT *
FROM `".$p."Tabe`;
")->cached(600, $is_clear_cache)->execute()->as_array('RegID');
if ($is_clear_cache)
{
HTTP::redirect(Request::current()->uri());
}
...
...
...
}
You can use Route filters (v3.3) or callbacks (3.1, 3.2) and set route params manually.
You can do it this way...
public function action_index()
{
// this will only be executed if you submmitted a form in your page
if(Arr::get($_POST,'search')){
$errors = '';
$data = Arr::extract($_POST,array('color','size'));
// you can now access data through the $data array:
// $data['color'], $data['size']
// perform validations here
if($data['color']=='') $error = 'Color is required';
elseif($data['size']=='') $error = 'Size is required';
if($error==''){
$this->request->redirect('search/'.$data['color'].'/'.$data['size']);
}
}
// load your search page view here
echo 'this is the search page';
}
Hope this helps you out.

Manipulating POST data to work with Symfony2 forms when used in a REST API

Background:
I am writing a RESTful API on symfony. I want the client to be able to post to a url using the content type application/json and post a json object of form that the controller action is looking for.
Im using a pretty basic controller setup for this. Lets assume for demonstration purposes that im trying to authenticate a simple username password combo.
public function loginAction( Request $request )
{
$user = new ApiUser();
$form = $this->createForm(new ApiUserType(), $user);
if ( "POST" == $request->getMethod() ) {
$form->bindRequest($request);
if ( $form->isValid() ) {
$em = $this->getDoctrine()->getEntityManager();
$repo = $this->getDoctrine()->getRepository('ApiBundle:ApiUser');
$userData = $repo->findOneByUsername($user->getUsername());
if ( is_object($userData) ) {
/** do stuff for authenticating **/
}
else{
return new Response(json_encode(array('error'=>'no user by that username found')));
}
else{
return new Response(json_encode(array('error'=>'invalid form')));
}
}
}
Now the issue that i have, and have i have tried var_dumping this till the cows come home, is that for what ever reason symfony does not want to take the application/json content-body and use that data to populate the form data.
Form name: api_apiuser
Fields: username, password
What would be the best way to handle this type of task. I am open to suggestions as long as i can get this working. Thanks for your time with the matter.
Youll need to access the RAW request body and then use json_decode. Youll probably need to change your bindRequest method to something like the following:
public function bindRequest(Request $request)
{
if($request->getFormat() == 'json') {
$data = json_decode($request->getContent());
return $this->bind($data);
} else {
// your standard logic for pulling data form a Request object
return parent::bind($request);
}
}
I havent really messed with SF2 yet so this is more guessing based on the API, exp. with sf1.x and things ive garnered from presentations on the framework. It might also be better to make a completely different method like bindJsonRequest so things are a bit more tidy.
Ive actually found a similar way to fix this, AFTER checking if the method is post and before binding the request to the form i do this:
if ( "POST" === $request->getMethod() ) {
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')){
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
$form->bindRequest($request);
/** Rest of logic **/
}
Yeah, what the form is waiting for during binding is an array containing keys that correspond to your ApiUser properties.
So if you send a POST request with the string:
{ username: 'user', password: 'pass' }
You will have to transform it into an array using json_decode for example:
$data = json_decode($request->getContent()); // $request->request->get('json_param_name');
Then you bind this array to the form using $form->bind($data);
The form will update your ApiUser properties corresponding to array's keys (username, password).
If you're building a RESTful json api, I would advice you to automatize this process using serializers/transformers, like https://github.com/schmittjoh/JMSSerializerBundle/blob/master/Resources/doc/index.rst

Categories