I have created an update password form and whenever I try to submit the data I got error like The class XXX was not found in the chain configured namespaces. What am I doing wrong in here? The error occurs when I try to save the data in the database. I have tried the answer from implementing update password
Here are my codes.
This is my ChangePasswordType.php
<?php
namespace RetailMapping\Bundle\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ChangePasswordType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('oldPassword', 'password');
$builder->add('newPassword', 'repeated', array(
'type' => 'password',
'invalid_message' => 'The password fields must match.',
'required' => true,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'RetailMapping\Bundle\UserBundle\Form\Model\ChangePassword',
));
}
/**
* #return string
*/
public function getName()
{
return 'retailmapping_bundle_userbundle_password_chnage';
}
}
This is my ChangePassword.php
<?php
namespace RetailMapping\Bundle\UserBundle\Form\Model;
use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
use Symfony\Component\Validator\Constraints as Assert;
class ChangePassword
{
/**
* #SecurityAssert\UserPassword(
* message = "Wrong value for your current password"
* )
*/
protected $oldPassword;
/**
* #Assert\Length(
* min = 6,
* minMessage = "Password should by at least 6 chars long"
* )
*/
protected $newPassword;
public function setOldPassword($oldPassword)
{
$this->oldPassword = $oldPassword;
}
public function getOldPassword()
{
return $this->oldPassword;
}
public function setNewPassword($newPassword)
{
$this->newPassword = $newPassword;
}
public function getNewPassword()
{
return $this->newPassword;
}
}
This is my UserController.php
<?php
namespace RetailMapping\Bundle\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use RetailMapping\Bundle\UserBundle\Form\ChangePasswordType;
use Symfony\Component\HttpFoundation\Request;
use RetailMapping\Bundle\UserBundle\Form\Model\ChangePassword;
class UserController extends Controller
{
public function editPasswordAction(Request $request)
{
$form = $this->createForm(new ChangePasswordType(), new ChangePassword());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($data);
$em->flush();
dump($form->getData());
die;
}
return $this->render('User/editPassword.html.twig', [
'form' => $form->createView(),
]);
}
}
By default your entity is mapped to Entity namespace.
DoctrineExtension code on github
protected function getMappingObjectDefaultName()
{
return 'Entity';
}
You need to place your ChangePassword.php within Entity folder.
UPDATE:
Similar question - you can look at
Related
I want to know how I can recover the current user in my FormType (EntityType)?
Currently, I can only retrieve the list of registered users but not the current (connected) user.
My current FormType
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class OneNewCarType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(
'author',
EntityType::class, [
'label' => 'Ville',
'class' => User::class,
'attr' => [
'class' => 'selectpicker'
],
'choice_label' => function ($author) {
return $author->getCity();
}
]
);
}
public function getBlockPrefix()
{
return 'oneNewCarType';
}
}
I know how to recover it directly in my controller. But, I do not know how to do it when one uses the stepper bundle CraueFormFlowBundle
This is my current controller
/**
* #Route("/classified/{id}/edit", name="classified_edit")
* #param CarVehicle $carVehicle
* #param ObjectManager $manager
* #param CreateVehicleFlow $createVehicleFlow
* #return RedirectResponse|Response
*/
public function edit(CarVehicle $carVehicle, ObjectManager $manager, CreateVehicleFlow $createVehicleFlow)
{
$flow = $createVehicleFlow;
$flow->bind($carVehicle);
$form = $flow->createForm();
if ($flow->isValid($form)) {
$flow->saveCurrentStepData($form);
if ($flow->nextStep()) {
$form = $flow->createForm();
} else {
$manager->persist($carVehicle);
$manager->flush();
$flow->reset();
$this->addFlash(
'success',
"Votre annonce <i>{$carVehicle->getId()}</i> a bien été mise à jour"
);
return $this->redirect($this->generateUrl('account_index'));
}
}
return $this->render('front/classified/edit_vehicle.html.twig', [
'form' => $form->createView(),
'flow' => $flow,
'carVehicle' => $carVehicle,
]);
}
Thanks for the help !
With Symfony\Component\Security\Core\Security you can get user where you want. Inject this into FormType and use $user = $this->security->getUser();
private Security $security;
public function __construct(Security $security)
{
$this->security = $security;
}
In Symfony 5, With use
Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface
you can get user where you want. Inject this into FormType and use
$user = $this->token->getToken()->getUser();
private $token;
public function __construct(TokenStorageInterface $token)
{
$this->token = $token;
}
Here is the situation:
I have an entity Property
class Property
{
/**
* #ORM\Id
* #ORM\Column(type="string")
* #ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="PropertyEquipment", inversedBy="properties")
*/
protected $propertyEquipments;
public function __construct()
{
$this->propertyEquipments = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function addPropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
{
$this->propertyEquipments[] = $propertyEquipment;
return $this;
}
public function removePropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
{
$this->propertyEquipments->removeElement($propertyEquipment);
}
public function getPropertyEquipments()
{
return $this->propertyEquipments;
}
}
And the entity PropertyEquipment:
class PropertyEquipment
{
/**
* #ORM\Id
* #ORM\Column(type="string")
* #ORM\GeneratedValue(strategy="UUID")
*/
protected $id;
/**
* #ORM\ManyToMany(targetEntity="Property", mappedBy="propertyEquipments")
*/
protected $properties;
/**
* #ORM\Column(type="string", length=100)
* #Gedmo\Translatable
*/
protected $equipmentName;
public function __construct()
{
$this->properties = new ArrayCollection();
}
/**
* Get id
*
* #return string
*/
public function getId()
{
return $this->id;
}
/**
* #return mixed
*/
public function getEquipmentName()
{
return $this->equipmentName;
}
/**
* #param mixed $equipmentName
*/
public function setEquipmentName($equipmentName)
{
$this->equipmentName = $equipmentName;
}
public function addProperty(Property $property)
{
$this->properties[] = $property;
return $this;
}
public function removeProperty(Property $property)
{
$this->properties->removeElement($property);
}
public function getProperties()
{
return $this->properties;
}
}
The form PropertyCreation
class PropertyCreation extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
//with this I see the values coming from DB in the template
->add("propertyEquipments", PropertyEquipmentCreation::class)
//with this it's empty :/
/*->add("propertyEquipments", CollectionType::class, array(
"entry_type" => PropertyEquipmentCreation::class,
))*/
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Property::class
));
}
}
Here is the form PropertyEquipmentCreation:
class PropertyEquipmentCreation extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('propertyEquipment', EntityType::class, [
'class' => 'AppBundle\Entity\PropertyEquipment',
'choice_label' => 'equipmentName',
'expanded' => true,
'multiple' => true
]);
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PropertyEquipment::class,
]);
}
}
And the controller
public function createPropertyAction(Request $request)
{
$property = new Property();
$form = $this->createForm(PropertyCreation::class, $property);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($property);
$entityManager->flush();
return $this->redirectToRoute('homepage');
}
return $this->render('form/owner_create_property.html.twig', ["form" => $form->createView()]);
}
My error:
Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Property#$propertyEquipments", got "Doctrine\Common\Collections\ArrayCollection" instead.
Must I transform these with something like class PropertyEquipmentTransformer implements DataTransformerInterface?
I think you should use getParent() function in PropertyEquipmentCreation and inherit from EntityType::class then put all your field configs in the configureOptions() function (remove the buildForm function) and it should work.
You are having this problem because it is a compound form in your implementation and no simple form and symfony is unable to resolve which field created inside the subform needs to be used as source for the entity field
First !
Big thanks to Nickolaus !
Here is the solution (PropertyEquipmentCreation):
namespace AppBundle\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PropertyEquipmentCreation extends AbstractType
{
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'AppBundle\Entity\PropertyEquipment',
'choice_label' => 'equipmentName',
'expanded' => true,
'multiple' => true,
]);
}
public function getParent()
{
return EntityType::class;
}
}
And for (PropertyCreation)
<?php
namespace AppBundle\Form;
use AppBundle\Form\Type\PropertyEquipmentCreation;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PropertyCreation extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', TextareaType::class)
->add('name', TextType::class)
->add("propertyEquipments", PropertyEquipmentCreation::class)
->add('save', SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Property::class
));
}
}
Many thanks !
Try using Doctrine ArrayCollection instead of ArrayCollections:
$this->propertyEquipments = new \Doctrine\Common\Collections\ArrayCollection();
This should work!
I have created an update password form and whenever I try to submit the data I got error like The class 'RetailMapping\Bundle\UserBundle\Form\Model\ChangePassword' was not found in the chain configured namespaces AppBundle\Entity, RetailMapping\Bundle\UserBundle\Entity, RetailMapping\Bundle\CatalogBundle\Entity, RetailMapping\Bundle\LocationBundle\Entity, RetailMapping\Bundle\ClassificationBundle\Entity, RetailMapping\Bundle\RetailOutletBundle\Entity, FOS\UserBundle\Model. What am I doing wrong in here? The error occurs when I try to save the data in the database.
Here are my codes.
This is my ChangePasswordType.php
<?php
namespace RetailMapping\Bundle\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ChangePasswordType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('oldPassword', 'password');
$builder->add('newPassword', 'repeated', array(
'type' => 'password',
'invalid_message' => 'The password fields must match.',
'required' => true,
'first_options' => array('label' => 'Password'),
'second_options' => array('label' => 'Repeat Password'),
));
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'RetailMapping\Bundle\UserBundle\Form\Model\ChangePassword',
));
}
/**
* #return string
*/
public function getName()
{
return 'retailmapping_bundle_userbundle_password_chnage';
}
}
This is my ChangePassword.php
<?php
namespace RetailMapping\Bundle\UserBundle\Form\Model;
use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
use Symfony\Component\Validator\Constraints as Assert;
class ChangePassword
{
/**
* #SecurityAssert\UserPassword(
* message = "Wrong value for your current password"
* )
*/
protected $oldPassword;
/**
* #Assert\Length(
* min = 6,
* minMessage = "Password should by at least 6 chars long"
* )
*/
protected $newPassword;
public function setOldPassword($oldPassword)
{
$this->oldPassword = $oldPassword;
}
public function getOldPassword()
{
return $this->oldPassword;
}
public function setNewPassword($newPassword)
{
$this->newPassword = $newPassword;
}
public function getNewPassword()
{
return $this->newPassword;
}
}
This is my UserController.php
<?php
namespace RetailMapping\Bundle\UserBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use RetailMapping\Bundle\UserBundle\Form\ChangePasswordType;
use Symfony\Component\HttpFoundation\Request;
use RetailMapping\Bundle\UserBundle\Form\Model\ChangePassword;
class UserController extends Controller
{
public function editPasswordAction(Request $request)
{
$form = $this->createForm(new ChangePasswordType(), new ChangePassword());
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($data);
$em->flush();
dump($form->getData());
die;
}
return $this->render('User/editPassword.html.twig', [
'form' => $form->createView(),
]);
}
}
There's no mention of an Entity in the post you linked. Because you made the class an Entity, it's become a database table, and fields like id's are expected.
Double check the answer you tried to implement.
For making a password update form you need to make PasswordUpdateModel and PasswordUpdateType, after processing form you can assign it to UserEntity fields.
I hope this helps.
I have a form type and an other form type include the first one in one of his fields.
The second form type is used to display a list of entities
The first form type:
<?php
namespace Test\GameBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Doctrine\ORM\EntityRepository;
class CityType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('nameEn')
->add('latitude')
->add('longitude')
->add('country','entity',array(
'class' => 'GeoQuizzGameBundle:Country',
'property' => 'nameEn',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c')
->orderBy('c.nameEn', 'ASC');
},
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Test\GameBundle\Entity\City'
));
}
/**
* #return string
*/
public function getName()
{
return 'test_gamebundle_city';
}
}
The second entity:
namespace Test\AdminBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Test\GameBundle\Form\CityType;
class CityListType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('cities','collection', array(
'type'=>new CityType(),
'allow_add' => true,
'by_reference' => false
))
;
}
/**
* #param OptionsResolverInterface $resolver
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Test\AdminBundle\Entity\CityList'
));
}
/**
* #return string
*/
public function getName()
{
return 'test_adminbundle_citylist';
}
}
and the form creation in the controller:
public function listAction(Request $request)
{
$cityRepository = $this->getDoctrine()->getRepository("GeoQuizzGameBundle:City");
//get continents
$cities = $cityRepository->findBy(
array(),
array('nameEn' => 'ASC')
);
$cityList = new CityList();
foreach($cities as $city){
$cityList->addCity($city);
}
$form = $this->createForm(new CityListType(),$cityList);
$form->handleRequest($request);
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
foreach ($cityList->getCities() as $city){
if(!$this->isCity($cities, $city)){
$em->persist($city);
}
}
$em->flush();
return $this->redirect($this->generateUrl('geo_quizz_admin_city_list'));
}
return $this->render('GeoQuizzAdminBundle:City:list.html.twig',array(
'form' => $form->createView()
));
}
I have 196 request for 124 fields because the country list is requery on each row, is there a solution to prevent it ?
I can do the query in the controller and pass my country array as argument of the form type, is it clean ?
You can use choice field type instead of entity. All you need to do is have choices parameter containing your list of countries.
$countryChoices is an associative array of countries which you can fetch once and use it in buildForm method. The way I would do that is making your form a service, and passing ObjectManager to contructor:
services.yml:
services:
your_form:
class: Test\GameBundle\Form\CityListType
arguments: [#doctrine.orm.entity_manager]
tags:
- { name: form.type, alias: yourFormAlias }
Your CityType class:
class CityType extends AbstractType
{
/**
* #param ObjectManager $objectManager
*/
public function __construct(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$countryChoices = array();
//by using result cache your query would be performed only once
$countries = $this->objectManager
->getRepository('GeoQuizzGameBundle:Country')
->createQueryBuilder('c')
->orderBy('c.nameEn', 'ASC')
->getQuery()
->useResultCache(true)
->getResult();
foreach($countries as $country) {
$countryChoices[$country->getId()] = $country->getNameEn();
}
$builder
->add('country','choice',array(
'choices' => $countryChoices,
'label' => 'Country',
))
;
}
}
You will also need to start call your form like a service.
Ok here is a quick overview of what I am trying to do. I have a "Client" entity with a relationship to a "ClientDomain" entity. I need to have a form that will show me a list of all the ClientDomains for a given client. In the controller I know what client i need to filter for but im unsure how to pass that information to the formBuilder.
Heres what i have so far:
//src/NameSpace/ClientBundle/Entity/Client.php
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
*/
class Client{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $client_id;
/**
* #ORM\Column(type="string")
*/
protected $name;
/**
* #ORM\OneToMany(targetEntity="ClientDomain", mappedBy="client")
*/
protected $domains;
...
}
And the form:
//src/LG/ClientBundle/Form/ClientDomainSelectionForm.php
namespace LG\ProjectBundle\Form\Projects;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ClientDomainSelectionForm extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('client_domain', 'entity', array(
'class' => 'LG\ClientBundle\Entity\ClientDomain',
'query_builder'=> function(EntityRepository $er) {
return $er->createQueryBuilder('cd')
/* NEEDS TO FIND DOMAINS BY CLIENT X */
},
'property' => 'domain',
'label' => 'Domain: '
));
}
}
And then finally the controller:
//src/LG/ClientBundle/Controller/DomainSelectorController.php
namespace LG/ClientBundle/Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use LG\ClientBundle\Entity\Client;
use LG\ClientBundle\Entity\ClientDomain;
use LG\ClientBundle\Entity\ClientActiveDomain;
use LG\ClientBundle\Form\ClientDomainSelectionForm;
/**
* #Route("")
*/
class DomainSelectorController extends Controller{
/**
* #Route("/client/{client_slug}/select-domain", name="lg.client.clientdomainselection.selectclient")
* #Template
*/
public function selectDomainAction(Request $request, Client $client){
$activeDomain = new ClientActiveDomain();
$form = $this->createForm(new ClientDomainSelectionForm(), $activeDomain );
if ($request->isMethod('POST')) {
$form->bind($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$em->persist($activeDomain );
$em->flush();
return $this->redirect(/*huge long url*/);
}
}
return array(
'form' => $form->createView(),
);
}
}
As you can see I have access to the client entity in the controller im just not sure how to give that to the form builder so that it will only return domains for the current client.
I Have found the answer, you just need to add a constructor to the form and pass in the client from the controller like so:
//src/LG/ClientBundle/Form/ClientDomainSelectionForm.php
namespace LG\ProjectBundle\Form\Projects;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class ClientDomainSelectionForm extends AbstractType {
protected $client;
public function __construct(Client $client) {
$this->client = $client;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$client = $this->client;
$builder->add('client_domain', 'entity', array(
'class' => 'LG\ClientBundle\Entity\ClientDomain',
'query_builder'=> function(\Doctrine\ORM\EntityRepository $er) use ($client) {
return $er->createQueryBuilder('cd')
->where('cd.client = :client')
->orderBy('cd.domain', 'ASC')
->setParameter('client',$client->getClientId());
},
'property' => 'domain',
'label' => 'Domain: '
));
}
}
And Then in the controller:
//src/LG/ClientBundle/Controller/DomainSelectorController.php
...
public function selectDomainAction(Request $request, Client $client){
...
$form = $this->createForm(new ClientDomainSelectionForm($client), $activeDomain );
...
}
...