symfony2 form without error is not valid - symfony

I have the following code in my controller extending BaseController, and that seems not to be working, but I am not able to see a decent error :
$responseFormatter = $this->getResponseFormatter();
$entity = new POI();
$form = $this->createForm(new POIType(), $entity);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $responseFormatter->successfullResponseFormat($entity)->getResponse();
}
$errors = $this->formErrorFormatter($form);
return $responseFormatter->badResponseFormat('entity.error', $errors)->getResponse();
I even tried the solution of $form->getErrors(true); , and it is empty on my return, so this post ( Symfony2 invalid form without errors ) haven't solved my issue.
Thanks

These may also be one of the causes of not being valid.
First: Not valid a METHOD
Inside `HttpFoundationRequestHandler
$name = $form->getName();
$method = $form->getConfig()->getMethod();
if ($method !== $request->getMethod()) {
return;
}
Form Submitted status is false
This makes your form not submitted. If the form's status is not submitted it will not be valid as well. Not only errors make your form invalid. Following code demonstrates it.
Inside isValid function
public function isValid()
{
if (!$this->submitted) {
return false;
}
if ($this->isDisabled()) {
return true;
}
if (count($this->getErrors(true)) > 0) {
return false;
}
return true;
}

Please try this one
$responseFormatter = $this->getResponseFormatter();
$entity = new POI();
$form = $this->createForm(new POIType(), $entity);
$form->handleRequest($request);
$form->isValid();
$form->getErrorsAsString();
exit;
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $responseFormatter->successfullResponseFormat($entity)->getResponse();
}
$errors = $this->formErrorFormatter($form);
return $responseFormatter->badResponseFormat('entity.error', $errors)->getResponse();
I hope getErrorsAsString() function show error if any error message are occurred during validate.

Or have you forget the following in your template?
{{ form_start(form) }}
If not, how have you render your form?

Related

Doctrine not getting newly added record

I have a function that does 2 things.
Saves an existing or a new item/record
Query and re-order items
The code algorithm is like this
public function doSomething($id = 0)
{
$em = $this->getEntityManagerFromSomewhere();
$service = $this->getSomeServiceFromSomewhere();
$repo = $em->getRepository(Item::class);
$conn = $em->getConnection();
$conn->beginTransaction();
if ($id) {
$item = new Item();
} else {
$item = $repo->find($id);
}
$em->persist($item);
$em->flush();
$items = $repo->getAllItems();
// changes are saved to the database
$service->rearrangeItems($items);
$conn->commit();
}
Now the issue I'm having with this is that, if it is a new Item, when we try to get all items, that new item is not included for some odd reason.
I've tried stuff on my own and the one that works for me is to insert
$em->clear(); // after flush
I am not sure if this is the best way to approach this or if I'm misusing this functionality. It works though, when I tested it.
public function doSomething($id = 0)
There is $id is default 0, Actually, your are creating item every time.
if ($id) {
$item = new Item();
$em->persist($item);
} else {
$item = $repo->find($id);
}
also, you don't need to persist if you don't update or create new Item.
Or the way that I understood.
if($id)
{
$item = $em->getRepository(Item::class)->find($id)
}
else
{
$item = new Item();
$em->persist($item);
}
$em->flush();

Access session variable from different controller in symfony

i want to create an array as a session table to put it empty in the beggining for my cart shop to display nothing as an empty cart and when i press AddtoCart i want get that array and do an array_push with the new items but i didn't know how to do it
This is the first controller when i create the array empty
public function FrontAction()
{
$pro=new Produit();
$pro->setNom('');
$pro->setQuantite(0);
$pro->setPrix(0);
$em = $this->getDoctrine()->getManager();
$sess=new Session();
$sess->setName('PANIER');
$sess=array('');
array_push($sess,$pro->getNom(),$pro->getQuantite(),$pro->getPrix());
$paniers = $em->getRepository(Panier::class)->findByUserId(1);
$produits = $this->getDoctrine()->getRepository(Produit::class)->findAll();
$boutiques = $this->getDoctrine()->getRepository(Boutique::class)->GetBestShopsDQL();
if ($paniers != null)
{
$prixTotal = 0;
foreach ($paniers as $panier) {
$prixTotal += $panier->getPrixTotal();
}
$resultCount = count($paniers);
return $this->render('BoutiqueBundle:FrontViews:ListBoutique.html.twig', array('produits' => $produits, 'boutiques' => $boutiques,'paniers' => $paniers, 'prixTotal' => $prixTotal,'resultCount' => $resultCount));
}
return $this->render('BoutiqueBundle:FrontViews:ListBoutique.html.twig', array('produits' => $produits, 'boutiques' => $boutiques,'sess'=>$sess));
}
and this is the second controller where i want to fill that empty array with new items
public function ajouterauPanierAction($id)
{
$ses=new Session();
$ses->getName('PANIER');
$test=array('');
$test=$ses;
// $user_id = $this->getUser()->getId(); //à modifier!!!!!
$em = $this->getDoctrine()->getManager();
$produit = $em->getRepository(Produit::class)->find($id);
$test = $em->getRepository(Panier::class)->findExistant($id, 1);
// $session->replace(array_push($produit,));
if(($produit != null)&&(empty($test)))
{
array_push($test,$produit->getNom(),$produit->getQuantite(),$produit->getPrix());
/* $panier = new Panier();
$panier->setProduitId($produit->getId());
$panier->setUserId(1); //à changer avec le fos
$panier->setDate(new \DateTime("now"));
$panier->setPrixTotal($produit->getPrix());
$em->persist($panier);
*/ $em->flush();
$msg = "success";
// return $this->redirectToRoute('Dashboard');
}
else
{
//return $this->render('BoutiqueBundle:FrontViews:404.html.twig');
$msg = "failure";
}
return new JsonResponse(array('msg' => $msg));
}
i didn't know how to do it correctly or if my idea is wrong so hope u guys got what i need to do
Here is how I am doing it in Symfony 4, (I think this part is unchanged). First I have declared my session keys as class constants on the entities to avoid collisions.
class Appointment
{
const SESSION_KEY = 'confirmed_app_entity_appointment';
...
}
Then in the controller use the SessionInterface and it will get autowired into your controller method with a typehinted parameter (SessionInterface $session). Symfony will handle starting the session, just set, get, and/or remove the key as needed.
use Symfony\Component\HttpFoundation\Session\SessionInterface;
...
public function confirmAppointment($first_name, $last_name, $time, SessionInterface $session)
{
...
$session->set(Appointment::SESSION_KEY, $appointment);
$session->set(StaffMember::SESSION_KEY_SELECTED_STAFF, $member);
...
if ($this->isConflict($appointment)) {
$session->remove(Appointment::SESSION_KEY);
$session->remove(StaffMember::SESSION_KEY_AUTH);
$this->addFlash('error', 'Failed to create Appointment, conflict found');
return $this->redirectToRoute('customer');
}
...
}
public function saveAppointment(SessionInterface $session)
{
if (!empty($session->get(Appointment::SESSION_KEY))) {
$appointment = $session->get(Appointment::SESSION_KEY);
}
...
}

Cancel oldest raw in DB after calling findAll() method

I have a table for users password recovery requests. These are his columns:
ID
idUser
createdDate
expiryDate
token
isExpired
If a User tries to make multiple requests I want to find all the rows with his ID, and if they are > 1, set them to isExpired = true.
Doing so, I want to consider as valid only the last request.
How can I achieve this?
This is how I'm doing it now, assuming that in the table there is only one row with his ID:
if ($request->isMethod('POST')) {
$form->handleRequest($request);
$newPassword = $form->get('password')->getData();
$currentToken = $request->query->get('token');
$em = $this->getDoctrine()->getManager();
$passwRecovery = $em->getRepository('\UserBundle\Entity\PasswordRecovery')->findOneBy(array('token' => $currentToken));
if (empty($passwRecovery)) {
return new Response ("<h3>Access denied!</h3>");
}
else {
if (new \DateTime('now') > $passwRecovery->getExpireDate())
{
return new Response ("<h3>Token expired!</h3>");
}
$idUser = $passwRecovery->getIdUser();
$userRecoverPassw = $em->getRepository('\UserBundle\Entity\User')->findOneBy(array('id' => $idUser));
$userRecoverPassw->setPassword($newPassword);
$em->persist($userRecoverPassw);
$em->flush();
return new Response ("<h3>Password reset ok!</h3>"); }
Consider I have 3 rows with the same idUser, if I use:
$passwRecovery = $em->getRepository('\UserBundle\Entity\PasswordRecovery')
->findAll(array('token' => $currentToken));
I will get 3 results. How can I set the isExpired = true only for the first two?
Thanks!
This is the solution that at the end worked for me, hope this can help. If there are any better ways to do what I'm posting here, I'm open to suggestions.
public function resetPasswordAction(Request $request) {
$form = $this->createFormBuilder()
->add('password', 'password')
->add('save', 'submit', ['label' => 'Send'])
->getForm();
if ($request->isMethod('POST')) {
$form->handleRequest($request);
$newPassword = $form->get('password')->getData();
$currentToken = $request->query->get('token');
$em = $this->getDoctrine()->getManager();
$passwRecoveryObject = $em->getRepository('\UserBundle\Entity\PasswordRecovery')->findOneBy(array('token' => $currentToken));
if (empty($passwRecoveryObject)) {
return new Response ("Impossible to execute the request!");
}
else {
if (new \DateTime('now') > $passwRecoveryObject->getExpireDate())
{
return new Response ("Token expired!");
}
$idUser = $passwRecoveryObject->getIdUser()->getId();
$userRecoverPassw = $em->getRepository('\UserBundle\Entity\PasswordRecovery')->findBy(array('idUser' => $idUser));
$end = end($userRecoverPassw); //$end is the last record of the password_recovery table
$count = count($userRecoverPassw); //count of the rows in password_recovery with the id of the current User
foreach ($userRecoverPassw as $element) { //here i'm setting to 1 the isExpired column for all the rows with the same id, except for the last one
if (--$count <= 0) {
break; }
$element->setIsExpired(1);
$em->persist($element);
$em->flush();
}
$userResetPassw = $em->getRepository('\UserBundle\Entity\User')->findOneBy(array('id' => $end->getIdUser()->getId())); //User that need to reset the password
if ($end->getIsExpired()==0) {
$userResetPassw->setPassword($newPassword);
$end->setIsExpired(1);
$em->persist($userResetPassw);
$em->flush();
$em->persist($end);
$em->flush();
return new Response ("Password succesfully updated!");
}
else { return new Response ("Expired link!");}
} }
return $this->render('UserBundle:AccountUser:reset_password.html.php', array(
'form' => $form->createView(),));
}

FOSRestBundle: just trying to return an empty form for new elements

I have this code to response with a form to create new customers:
public function getNewAction()
{
$form = new CustomerType();
$view = $this->view($form, 200)
->setTemplate("PlacasFrontendBundle:Customer:newCustomer.html.twig")
;
return $this->handleView($view);
}
but when I request http://crm/app_dev.php/new the only I get rendered on browser is this:
{}
NOTE: I don't have any problems with this function below. I mean it returns a jsoned list of customers correctly:
public function getCustomersAction()
{
$repository = $this->getDoctrine()->getRepository('PlacasFrontendBundle:Customer');
$data = $repository->findAll();
$view = $this->view($data, 200)
->setTemplate("PlacasFrontendBundle:Customer:getUsers.html.twig")
->setTemplateVar('users')
;
return $this->handleView($view);
}
public function getNewAction()
{
$form = new CustomerType();
$view = $this->view($form, 200)
->setTemplate("PlacasFrontendBundle:Customer:newCustomer.html.twig")
->setHeader('Content-Type', 'text/html')
;
return $this->handleView($view);
...
You need to set the proper Content-Type header.

Symfony2 form validation without createFormBuilder

I am trying to validate the form that I have made myself in .twig file.I am not creating form using createFormBuilder. This is my Controller Code that is call for both case 1) for view 2) after submitting the form.
public function cart_newAction(Request $request)
{
$entity = new Product();
$errors = '';
if ($request->getMethod() == 'POST')
{
$validator = $this->get('validator');
$errors = $validator->validate($entity);
if (count($errors) > 0) {
echo 'Error';
}
else {
echo 'Success';
}
}
return $this->render('CartCartBundle:Cart:Add.html.twig', array('errors' => $errors ));
}
this is view file and I am showing errors like this
Add.html.twig
{% for error in errors %}
{{error}}
{% endfor %}
I have set the error in validation.yml file for name that cannot be blank.
So now when I run the view page it every times show the error after I submit the form.
If no error it should not display me the error just show the blank error.
Note:Is there any better way that I can do this so please share it.Remember that I am doing it without createFormBuilder
UPDATE
It always show me Error.Even if my form is valid and don't missing any field.
If you want to make the form yourself then you can't validate it using the Syfmony form validator. You need to use a simple PHP validation Server-side. Something like this
if ($request->getMethod() == 'POST')
{
$username = $_POST['username'];
if ($username == '')
{
// set error message here
}
}
Ok let me be clear. I gonna give you tow solutions, the first is the best and the most proper way:
1) Generate your EntityForm Type: bin/console make:form or d:g:form command.
2) Then just add some few lines to submit and get the errors.
public function cart_newAction(Request $request)
{
$entity = new Product();
$form = $this->createForm(EntityType::class, $entity);
$form->submitForm($request->request->all(), false);
if ($request->getMethod()->isPost())
{
if ($form->isValid()) {
echo 'Error';
}
else {
echo 'Success';
}
}
return $this->render('CartCartBundle:Cart:Add.html.twig', [
'errors' => $form->getErrors(),
]);
}
The second solution is bind your data into your entity object because we need to set the data into our object.
1) First step create a private fonction in your current class to bind all the submited data:
private function bindEntityValues(Product $entity, array $data) {
foreach ($data as $key => $value){
$funcName = 'set'+ucwords($key);
if(method_exists($entity, $funcName)) $entity->$funcName($value);
}
}
Then your cart_newAction should be like this:
public function cart_newAction(Request $request)
{
$entity = new Product();
$this->bindEntityValues(entity, $request->request->all());
$errors= $this->get('validator')->validate($entity)
if (count($errors) > 0) {
echo 'Error';
}
else {
echo 'Success';
}
}
return $this->render('CartCartBundle:Cart:Add.html.twig', ['errors' => $errors]);
}
Wish this helped you to have a clear vision.
You must check if $errors is empty or not :
if (count($errors) > 0) {
return $this->render('CartCartBundle:Cart:Add.html.twig', array('errors' => $errors ));
} else {
return $this->render('CartCartBundle:Cart:Add.html.twig');
}
See the doc here.

Resources