Hello I'm trying to make user update/editing system with symfony FOSUserBundle and I have little problem
currently I'm able to load existing username and email with following code:
public function editAction(Request $request, $id)
{
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('id' => $id));
$form = $this-> createFormBuilder($user)
->add('username')
->add('email')
->add('save', 'submit')
->getForm();
$form->setData($user);
$userManager->updateUser($user);
return $this->render('PRACTestBundle:Default:edit.html.twig', array('form' => $form->creaveView()));
}
even though I'm able to submit form it won't save changes. Can someone help me out and tell how to do it? Thanks for your time!
It seems like you're mixing update action with edit page. I'm confused, why are you trying to update user just after loading data?
Here's how You should create controller with Show and Edit actions for currently logged user:
https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/ProfileController.php
If you're going to edit other user accounts, then change editAction from this URL to:
public function editAction(Request $request, $id)
{
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserBy(array('id' => $id));
// the rest of the stuff
(...)
}
Let me know if this helps.
I solved this out..
public function editAction(Request $request, $id)
{
$userManager = $this->get('fos_user.user_manager');
$form = $this-> createFormBuilder($user)
->add('username')
->add('email')
->add('save', 'submit')
->getForm();
$form->handleRequest($request);
if ($form->isValid())
{
$userManager->updateUser($user);
}
return $this->render('PRACTestBundle:Default:edit.html.twig', array('form' => $form->creaveView()));
}
Related
I'm trying to put a value in form created by formbuilder, i took the value from another twig file by the request, and i'm trying to use $form->setData(array('field'=>value));
Code controller:
public function ModifierGestionMatchAction(Request $request)
{
$id = $request->get('id');
$idmatch = $request->get('idm');
$em = $this->getDoctrine()->getManager();
$type = $em->getRepository("MainBundle:ReservationGestionStock")
->find($id);
$match = $em->getRepository("MainBundle:Match")
->findOneByid($idmatch);
$form = $this->createForm(ReservationGestionStockType::class, $type);
$form->setData(array('hotel'=>null));
$form->setData(array('match'=>$match));
$form->handleRequest($request);
if($form->isValid()){
$em->persist($type);
$em->flush();
return $this->redirectToRoute("ReservationGestionStockAfficher");
}
return $this->render('MainBundle:GestionStock:GestionStockModifierMatch.html.twig',
array(
"form" => $form->createView(),
"match" => $match
));
}
my form code:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('hotel',HiddenType::class)
->add('match',HiddenType::class)
->add('nb')
->add('nbr')
->add('Valider', SubmitType::class)
->add('Reset', ResetType::class);
}
Notice: the hotel and match are 2 entitys, i'm having problem with setData() for match, i tried to setdata of idmatch but its the same problem," the form isnt valid "
$form->get('hotel')->setData('John');
$form->get('match')->setData($match);
After submission just do that,
$type = $form->getData(); $type->setHotel($hotel); $type->setMatch($match); then persist and flush $type
i did this and its working, but i think it's so weird ... anyway thanks everyone for replying me.
if ($form->isSubmitted()) {
$gestion= new ReservationGestionStock();
$gestion->setMatch(null);
$gestion->setNb($form->getData()->getNb('nb'));
$gestion->setNbr($form->getData()->getNbr('nbr'));
$gestion->setHotel($hotel);
$em->persist($hotel);
$em->flush();
return $this->redirectToRoute("ReservationGestionStockAfficher");
}
Thanks in advance to those who want to help me. I'm learning symfony 4 and I'm testing to see how to update a database by taking data from a form. So I made sure that it looked for a table on the base of the id and that it filled the form with the correct values of the form. But when I submit, the form-> isSubmitted condition is never verified. Do you have any suggestions?
public function updateArticle(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$article = $em->getRepository(Article::class)->find($id);
if (!$article) {
throw $this->createNotFoundException(
'No article found for id '.$id
);
}
$articletext = $article->getArticle();
$title = $article->getTitle();
$image = $article->getFeatureimage();
$category = $article->getCategory();
$author = $article->getAuthor();
$article->setArticle($articletext);
$article->setTitle($title);
$article->setFeatureimage($image);
$article->setCategory($category);
$article->setAuthor($author);
$form = $this->createFormBuilder($article)
->add('article', TextareaType::class)
->add('title', TextType::class)
->add('featureimage', FileType::class, array('data_class' => null,'required' => true))
->add('category', TextType::class)
->add('author', TextType::class)
->add('save', SubmitType::class, array('label' => 'Inserisci articolo'))
->getForm();
if ($form->isSubmitted()) {
$article = $form->getData();
print_r($article);
return $this->redirectToRoute('blog');
}
else
return $this->render('insert.html.twig', array(
'form' => $form->createView(),
));
}
Your forgot a line that handle the data.
Look at the doc
Add this line before the if condition:
//form creation as you did but it's better to construct the form via the FormType
$form->handleRequest($request);
if ($form->isSubmitted()){
//Do some stuff
repository with issue
I have a form for entity User with email field:
->add('email', EmailType::class, [
'constraints' => [
new NotBlank(),
new Email([
'checkMX' => true,
])
],
'required' => true
])
when i'm editing email to something like test#gmail.com1 and submit form it shows me error "This value is not a valid email address." THat's ok, but after that symfony populate wrong email into token and when i'm going to any other page or just reload page, i'm getting this:
WARNING security Username could not be found in the selected user
provider.
i think question is: why symfony populate wrong Email that failed validation into token and how i could prevent it?
controller:
public function meSettingsAction(Request $request)
{
$user = $this->getUser();
$userUnSubscribed = $this->getDoctrine()->getRepository('AppBundle:UserUnsubs')->findOneBy(
[
'email' => $user->getEmail(),
]
);
$form = $this->createForm(UserSettingsType::class, $user);
$form->get('subscribed')->setData(!(bool)$userUnSubscribed);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/**
* #var $user User
*/
$user = $form->getData();
/** #var UploadedFile $avatar */
$avatar = $request->files->get('user_settings')['photo'];
$em = $this->getDoctrine()->getManager();
if ($avatar) {
$avatar_content = file_get_contents($avatar->getRealPath());
$avatarName = uniqid().'.jpg';
$oldAvatar = $user->getPhoto();
$user
->setState(User::PHOTO_STATE_UNCHECKED)
->setPhoto($avatarName);
$gearmanClient = $this->get('gearman.client');
$gearmanClient->doBackgroundDependsOnEnv(
'avatar_content_upload',
serialize(['content' => $avatar_content, 'avatarName' => $avatarName, 'oldAvatar' => $oldAvatar])
);
}
$subscribed = $form->get('subscribed')->getData();
if ((bool)$userUnSubscribed && $subscribed) {
$em->remove($userUnSubscribed);
} elseif (!(bool)$userUnSubscribed && !$subscribed) {
$userUnSubscribed = new UserUnsubs();
$userUnSubscribed->setEmail($form->get('email')->getData())->setTs(time());
$em->persist($userUnSubscribed);
}
$user->setLastTs(time());
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
$this->get('user.manager')->refresh($user);
return $this->redirectToRoute('me');
}
return $this->render(
':user:settings.html.twig',
[
'form' => $form->createView(),
]
);
}
UPD:
it works fine if i change in OAuthProvider:
/**
* #param \Symfony\Component\Security\Core\User\UserInterface $user
*
* #return \Symfony\Component\Security\Core\User\UserInterface
*/
public function refreshUser(UserInterface $user)
{
return $this->loadUserByUsername($user->getName());
}
to:
/**
* #param \Symfony\Component\Security\Core\User\UserInterface $user
*
* #return \Symfony\Component\Security\Core\User\UserInterface
*/
public function refreshUser(UserInterface $user)
{
return $this->userManager($user->getId());
}
but it seems to be dirty hack.
Thanks.
Your user token seems to be updated by the form, even if the email constraint stop the flush.
Can you check if your form past the isValid function ?
You can maybe try to avoid it with an event listener or a validator.
With an event SUBMIT you should be able to check the email integrity, and then add a FormError to avoid the refreshUser.
This is a tricky one, thanks to the repository it was easier to isolate the problem. You are binding the user object form the authentication token to the createForm() method. After the
$form->handleRequest($request)
call the email off the token user object is updated.
I first thought to solve this by implementing the EquatableInterface.html in the User entity but this did not work, as the compared object already had the wrong email address set.
It may also be useful to implement the EquatableInterface interface, which defines a method to check if the user is equal to the current user. This interface requires an isEqualTo() method.)
Than I thought about forcing a reload of the user from the db and resetting the security token, but in the it came to my mind, that it might be sufficient to just refresh the current user object from the database in case the form fails:
$this->get('doctrine')->getManager()->refresh($this->getUser());`
In your controller, this would solve your issue.
/**
* #Route("/edit_me", name="edit")
* #Security("has_role('ROLE_USER')")
*/
public function editMyselfAction(Request $request) {
$form = $this->createForm(User::class, $this->getUser());
if ($request->isMethod(Request::METHOD_POST)) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
} else {
$this->get('doctrine')->getManager()->refresh($this->getUser());
}
}
return $this->render(':security:edit.html.twig',['form' => $form->createView()]);
}
Alternative solution
The issue at the Symfony repository resulted in some valuable input about Avoiding Entities in Forms and
Decoupling Your Security User which provides a more complex approach for a solution to your problem.
I'm using Symfony2 with FOSUserBundle, the problem I have encountered was in editing a user account, when I tried to edit a specific user account, the retrieved user info is correct but when I tried to update the retrieved user info, the currently logged account would be the one being edited not the retrieved user account, how is it possible? What's wrong with my code?
ProfileController :
//edit user
public function editUserAction($id, Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $em->getRepository('MatrixUserBundle:User')->find($id);
if (!is_object($user)) {
throw new AccessDeniedException('This user does not have access to this section.');
}
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.profile.form.factory');
$form = $formFactory->createForm();
$form->setData($user);
$form->handleRequest($request);
if ($form->isValid()) {
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
$userManager->updateUser($user);
$session = $this->getRequest()->getSession();
$session->getFlashBag()->add('message', 'Successfully updated');
$url = $this->generateUrl('matrix_edi_viewUser');
$response = new RedirectResponse($url);
}
return $this->render('FOSUserBundle:Profile:edit.html.twig', array(
'form' => $form->createView()
));
}
After the given user is correctly updated, you are returning a redirection to a custom route.
I guess the route matrix_edi_viewUser is an override of the original FOSUB\ProfileController::showAction.
Also, you have to create a specific showUserAction and pass it the updated user as argument.
The following code should works :
public function showUserAction($id)
{
$user = $em->getDoctrine()
->getManager()
->getRepository('MatrixUserBundle:User')
->find($id);
if (!is_object($user)) {
throw new AccessDeniedException('This user does not have access to this section.');
}
return $this->render('FOSUserBundle:Profile:show.html.twig', array('user' => $user));
}
The route :
matrix_edi_viewUser:
path: /users/{id}/show
defaults: { _controller: MatrixUserBundle:Profile:showUser }
And in your editAction, change your redirection to :
$url = $this->generateUrl('matrix_edi_viewUser', array('id' => $user->getId());
$response = new RedirectResponse($url);
Now, the user informations displayed in show will be the informations of the updated user.
I currently have a script in Symfony where I generate a form in a controller. This form shows the content of the Entity "Page". If the user edits the form, and submits it, the form adjusts the corresponding data in the database.
/**
* Webpage allowing user to edit a page and her attributes
*
* #Route("/edit")
*/
public function editAction(Request $request)
{
/*
* Get an array of all the current pages stored in the database.
*
* foreach loop through each website and create a seperate form for them
*
*/
$em = $this->getDoctrine()->getManager();
$pages = $em->getRepository(Page::class)->findAll();
foreach ($pages as $page) {
$editform= $this->createFormBuilder($page)
->add('name', 'text')
->add('location', 'url')
->add('displayTime', 'integer')
->add('save', 'submit', array(
'label' => 'Edit page'
))
->getForm();
$editform->handleRequest($request);
if ($editform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->flush();
return new Response('Page edited successfully - immediately effective');
}
}
return $this->render('WalldisplayBundle:Walldisplay:edit.html.twig',
array(
'editform' => $editform->createView()
));
}
Unfortunately, this only prints a form with the last entry in the database. What I'd like is to have a form created for -every- entry in the database, not just the last one. I've tried iterating through the Doctrine repository, no luck however. How could I solve this problem?
Maybe it will work. I have not tested.
/**
* Webpage allowing user to edit a page and her attributes
*
* #Route("/edit")
*/
public function editAction(Request $request)
{
/*
* Get an array of all the current pages stored in the database.
*
* foreach loop through each website and create a seperate form for them
*
*/
$em = $this->getDoctrine()->getManager();
$pages = $em->getRepository(Page::class)->findAll();
foreach ($pages as $key=>$page) {
$editforms[$key] = $this->createFormBuilder($page)
->add('name', 'text')
->add('location', 'url')
->add('displayTime', 'integer')
->add('save', 'submit', array(
'label' => 'Edit page'
))
->getForm();
foreach($editforms as $editform){
$editform->handleRequest($request);
if ($editform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->flush();
}
}
return new Response('Page edited successfully - immediately effective');
}
foreach($editforms as $editform){
$editform->handleRequest($request);
if ($editform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->flush();
}
foreach($editforms as $editform){
$arrayForm[$editform] = $editform->createView();
}
return $this->render('WalldisplayBundle:Walldisplay:edit.html.twig', $arrayForm);
}