I'm using Symfony 5.3.7, and using the #Assert annotations, attempting to validate a new user upon registering. Trying to understand the docs however not getting anywhere. Ideally I'd like to be able to understand how to validate an entity using these annotations. I've tried using a separate class, and got nowhere with understanding, although I do want to go down this route in case i reuse the component elsewhere. (I'd rather not validate in the form, but if i have to I can)
Entity
class User implements UserInterface
{
use TimestampableEntity;
/**
* #var int
*
* #ORM\Id()
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(name="intUserId", type="integer", nullable=false)
*/
private int $id;
/**
* #var string
*
* #ORM\Column(name="strFirstName", type="string", nullable=false)
*
* #Assert\NotBlank
* #Assert\Length(
* min = 2,
* max = 50,
* minMessage = "Your first name must be at least {{ limit}} characters long",
* maxMessage = "Your first name cannot be longer than {{ limit }} characters"
* )
*/
private string $firstName;
/**
* #var string
*
* #ORM\Column(name="strLastName", type="string", nullable=false)
*
* #Assert\NotBlank
* #Assert\Length(
* min = 2,
* max = 50,
* minMessage = "Your first name must be at least {{ limit}} characters long",
* maxMessage = "Your first name cannot be longer than {{ limit }} characters"
* )
*/
private string $lastName;
/**
* #var string
*
* #ORM\Column(name="strUsername", type="string", nullable=false)
*
* #Assert\Unique()
* #Assert\Length(
* min = 2,
* max = 15,
* minMessage = "Your first name must be at least {{ limit}} characters long",
* maxMessage = "Your first name cannot be longer than {{ limit }} characters"
* )
*/
private string $username;
/**
* #var string
*
* #ORM\Column(name="strPassword", type="string", nullable=false)
*
* #Assert\NotNull()
* #Assert\Regex(pattern = "^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{8,}$")
*
* #SecurityAssert\UserPassword(message = "Password is incorrect, please try again")
*/
private string $password;
/**
* #var string
*
* #ORM\Column(name="strEmail", type="string", nullable=false)
*
* #Assert\Unique()
* #Assert\Regex(pattern = "\b[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}\b")
*/
private string $email;
/**
* #var boolean
*
* #ORM\Column(name="bolAcceptTermsConditions", type="bool", nullable=false)
*
* #Assert\NotNull()
*/
private bool $acceptTermsAndConditions;
/**
* #var boolean
*
* #ORM\Column(name="bolAcceptPrivacyPolicy", type="bool", nullable=false)
*
* #Assert\NotNull()
*/
private bool $acceptPrivacyPolicy;
/**
* #var boolean
*
* #ORM\Column(name="bolEmailOptIn", type="bool", nullable=false)
*
* #Assert\NotNull()
*/
private bool $emailOptIn;
/**
* User constructor.
*
* #param string $firstName
* #param string $lastName
* #param string $username
* #param string $email
* #param string $password
*/
public function __construct(
string $firstName,
string $lastName,
string $username,
string $email,
string $password,
bool $acceptTermsAndConditions = false,
bool $acceptPrivacyPolicy = false,
bool $emailOptIn = false
) {
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->username = $username;
$this->email = $email;
$this->password = $password;
$this->acceptTermsAndConditions = $acceptTermsAndConditions;
$this->acceptPrivacyPolicy = $acceptPrivacyPolicy;
$this->emailOptIn = $emailOptIn;
$this->dtmAdded = Carbon::now();
}
Ideally I'd pass in the new entity or the array, either create the entity in the validator or similar
Controller
public function register(Request $request): Response
{
$registrationForm = $this->createForm(RegistrationFormType::class);
$registrationForm->handleRequest($request);
if ($registrationForm->isSubmitted() && $registrationForm->isValid()) {
$newUserData = $registrationForm->getData();
$user = new User(
$newUserData['firstName'],
$newUserData['lastName'],
$newUserData['email'],
$newUserData['username'],
$newUserData['password'],
$newUserData['termsConditions'],
$newUserData['privacyPolicy'],
$newUserData['emailFrequency']
);
return new RedirectResponse($request->headers->get('referer'));
}
return new RedirectResponse($request->headers->get('referer'));
}
Form
<?php
declare(strict_types=1);
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class RegistrationFormType extends AbstractType
{
public const FORM_NAME = 'registrationForm';
/**
* Form Builder for Registration Form
*
* #param FormBuilderInterface $builder
* #param array $options
*
* #return void
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('firstName', TextType::class, [
'label' => 'Firstname:',
'required' => true,
'attr' => [
'class' => 'form-input input-type-text',
'placeholder' => 'John',
],
]);
$builder->add('lastName', TextType::class, [
'label' => 'Lastname:',
'required' => true,
'attr' => [
'class' => 'form-input input-type-text',
'placeholder' => 'Doe'
],
]);
$builder->add('email', EmailType::class, [
'label' => 'Email:',
'required' => true,
'attr' => [
'class' => 'form-input input-type-email',
'placeholder' => 'example#example.com'
]
]);
$builder->add('username', TextType::class, [
'label' => 'Username:',
'required' => true,
'attr' => [
'class' => 'form-input input-type-text',
]
]);
$builder->add('password', PasswordType::class, [
'label' => 'Password:',
'required' => true,
'attr' => [
'class' => 'form-input input-type-email',
]
]);
$builder->add('termsConditions', CheckboxType::class, [
'label' => 'I accept the terms & conditions',
'required' => true,
]);
$builder->add('privacyPolicy', CheckboxType::class, [
'label' => 'I have read and understood the privacy policy',
'required' => true,
]);
$builder->add('emailFrequency', ChoiceType::class, [
'label' => 'Opt in to emails:',
'multiple' => false,
'expanded' => true,
'choices' => [
'Yes' => true,
'No' => false,
],
]);
}
/**
* #param OptionsResolver $resolver
*
* #return void
*/
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([]);
}
/**
* #return string
*/
public function getBlockPrefix(): string
{
return self::FORM_NAME;
}
}
so the issue is that you are not passing the new User object to the form, so the validation will not happen in this case.
What you can do to fix this is, declare the data_class for the form to be User in this case
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
And when you create the form in the action you need to pass a new User object to it like:
$user = new User();
$registrationForm = $this->createForm(RegistrationFormType::class, $user);
And you can remove the part where you instantiate and send data to the user entity
$user = new User(
$newUserData['firstName'],
$newUserData['lastName'],
$newUserData['email'],
$newUserData['username'],
$newUserData['password'],
$newUserData['termsConditions'],
$newUserData['privacyPolicy'],
$newUserData['emailFrequency']
);
instead of that, you should just use the entity manager to save the new user
, for that, you need to inject the entity manager, like so:
public function register(Request $request, EntityManagerInterface $entityManager): Response
and just use it to save the user object into the database
if ($registrationForm->isSubmitted() && $registrationForm->isValid()) {
$entityManager->persist($user);
$entityManager->flush();
}
Related
I am trying to submit a JSON through a complex form. I can't figure out what I am missing. The "normal" form is functioning. I am able to get serialized data with groups.
Class TaskBoard
class TaskBoard
{
/**
* #var integer $id id
*
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var \DateTime $createdTime createdTime
*
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $createdTime;
/**
* #var \DateTime $lastUpdatedTime lastUpdatedTime
*
* #ORM\Column(type="datetime", nullable=true)
* #Assert\DateTime()
*/
private $lastUpdatedTime;
/**
* #var string $name name
*
* #ORM\Column(type="string", length=20)
* #Assert\Type("string")
* #Assert\NotBlank()
* #Assert\Length(
* min = 2,
* max = 20,
* minMessage = "The name must be at least {{ limit }} characters long",
* maxMessage = "The name cannot be longer than {{ limit }} characters"
* )
*/
private $name;
/**
* #var App\Entity\User $user user
*
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="taskboards", cascade={"persist"})
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #var string $description description
*
* #ORM\Column(type="text", nullable=true)
* #Assert\Type("string")
*/
private $description;
/**
* #var App\Entity\Status $status status
*
* #ORM\ManyToOne(targetEntity="App\Entity\Status", inversedBy="taskboards", cascade={"persist"})
* #ORM\JoinColumn(name="status_id", referencedColumnName="id", nullable=false)
*/
private $status;
/**
* #var boolean $completed completed
*
* #ORM\Column(type="boolean")
*/
private $completed;
/**
* #var \DateTime $deadLine deadLine
*
* #ORM\Column(type="date", nullable=true)
* #Assert\DateTime()
* #Assert\GreaterThanOrEqual("today")
*/
private $deadLine;
Class Status
class Status
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=20)
*/
private $name;
/**
* #ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="status", cascade={"persist"})
*/
public $taskboards;
Class User
class User extends BaseUser
{
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="App\Entity\TaskBoard", mappedBy="user", cascade={"persist"})
*/
public $taskboards;
Form
class TaskBoardType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('user', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
)
)
->add('description', TextareaType::class, array(
'required' => false
))
->add('status', EntityType::class, array(
'class' => Status::class,
'choice_label' => 'name',
)
)
->add('deadLine', DateTimeType::class)
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => TaskBoard::class,
'csrf_protection' => false,
]);
}
Controller
class TaskBoardAPIController extends AbstractController {
public function postTaskBoard(Request $request) {
$form = $this->createForm(TaskBoardType::class, new TaskBoard());
$data = json_decode(
$request->getContent(), true
);
var_dump($data);
$form->submit($data);
if (!$form->isValid()) {
return new JsonResponse(
[
'status' => 'error',
'errors' => $form->getErrors(),
'form' => $form,
], JsonResponse::HTTP_BAD_REQUEST
);
}
$this->entityManager->persist($form->getData());
$this->entityManager->flush();
return new JsonResponse(
[
'status' => 'ok',
], JsonResponse::HTTP_CREATED
);
}
JSON sent
{
"name": "XXX",
"user": {
"id": 1,
"username": "BFA"
},
"description": "XXXXXXXXXXXXXXX",
"status": {
"id": 1,
"name": "To Do"
},
"completed": false
}
The form is not valid and blank in the JsonResponse.
I based myself on : https://codereviewvideos.com/course/beginners-guide-back-end-json-api-front-end-2018/video/symfony-4-json-api-form-submission
and Deserialize an entity with a relationship with Symfony Serializer Component
Thanks for your help.
What was wrong was the JSON input.
The form does this :
class TaskBoardType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('name', TextType::class)
->add('user', EntityType::class, array(
'class' => User::class,
'choice_label' => 'username',
)
)
->add('description', TextareaType::class, array(
'required' => false
))
->add('status', EntityType::class, array(
'class' => Status::class,
'choice_label' => 'name',
)
)
->add('deadLine', DateTimeType::class)
;
}
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'data_class' => TaskBoard::class,
'csrf_protection' => false,
]);
}
When checking the code generated from the form, this is the result :
<div>
<label for="task_board_user" class="required">User</label>
<select id="task_board_user" name="task_board[user]">
<option value="1">XXX</option>
<option value="2">XXX</option>
</select>
</div>
Thus the form is expecting directly an INT/ID.
By changing the JSON as follow it goes through validation :
{
"name": "XXXO",
"user": 1,
"description": "XXXXXXXXXXXXXXX",
"status": 1
}
Your forgot to handle and get form submission.
Note that you will need to get request data using something like
$form = $this->createFormBuilder($task)
... add fields
->getForm();
$form->handleRequest($request); // handling request
if ($form->isSubmitted() && $form->isValid()) {
// $form->getData() holds the submitted values
// but, the original `$task` variable has also been updated
$task = $form->getData();
// ... perform some action, such as saving the task to the database
// for example, if Task is a Doctrine entity, save it!
// $entityManager = $this->getDoctrine()->getManager();
// $entityManager->persist($task);
// $entityManager->flush();
return $this->redirectToRoute('...');
}
for more, see Handling Form Submissions
I am using Oro Platform and AccountBundle (OroCRM).
I want to remove (hide) social fields, and customize the address for my location (hide unnecessary fields). How can I do this? What to edit in code? Custom fields (created in ui) can be freely edited. The problem is with system fields.
Can I edit views (twig.html)? Is there another way? What is good practice?
UserBundle/Form/Type/UserType.php
<?php
namespace Oro\Bundle\UserBundle\Form\Type;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\SecurityContextInterface;
use Oro\Bundle\FormBundle\Form\Type\OroBirthdayType;
use Oro\Bundle\SecurityBundle\SecurityFacade;
use Oro\Bundle\UserBundle\Entity\User;
use Oro\Bundle\UserBundle\Form\EventListener\UserSubscriber;
use Oro\Bundle\UserBundle\Form\Provider\PasswordFieldOptionsProvider;
class UserType extends AbstractType
{
/** #var SecurityContextInterface */
protected $security;
/** #var SecurityFacade */
protected $securityFacade;
/** #var bool */
protected $isMyProfilePage;
/** #var PasswordFieldOptionsProvider */
protected $optionsProvider;
/**
* #param SecurityContextInterface $security Security context
* #param SecurityFacade $securityFacade
* #param Request $request Request
* #param PasswordFieldOptionsProvider $optionsProvider
*/
public function __construct(
SecurityContextInterface $security,
SecurityFacade $securityFacade,
Request $request,
PasswordFieldOptionsProvider $optionsProvider
) {
$this->security = $security;
$this->securityFacade = $securityFacade;
$this->isMyProfilePage = $request->attributes->get('_route') === 'oro_user_profile_update';
$this->optionsProvider = $optionsProvider;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->addEntityFields($builder);
}
/**
* {#inheritdoc}
*/
public function addEntityFields(FormBuilderInterface $builder)
{
// user fields
$builder->addEventSubscriber(new UserSubscriber($builder->getFormFactory(), $this->security));
$this->setDefaultUserFields($builder);
if ($this->securityFacade->isGranted('oro_user_role_view')) {
$builder->add(
'roles',
'entity',
[
'property_path' => 'rolesCollection',
'label' => 'oro.user.roles.label',
'class' => 'OroUserBundle:Role',
'property' => 'label',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.role <> :anon')
->setParameter('anon', User::ROLE_ANONYMOUS)
->orderBy('r.label');
},
'multiple' => true,
'expanded' => true,
'required' => !$this->isMyProfilePage,
'read_only' => $this->isMyProfilePage,
'disabled' => $this->isMyProfilePage,
'translatable_options' => false
]
);
}
if ($this->securityFacade->isGranted('oro_user_group_view')) {
$builder->add(
'groups',
'entity',
[
'label' => 'oro.user.groups.label',
'class' => 'OroUserBundle:Group',
'property' => 'name',
'multiple' => true,
'expanded' => true,
'required' => false,
'read_only' => $this->isMyProfilePage,
'disabled' => $this->isMyProfilePage,
'translatable_options' => false
]
);
}
$this->addOrganizationField($builder);
$builder
->add(
'plainPassword',
'repeated',
[
'invalid_message' => 'oro.user.message.password_mismatch',
'type' => 'password',
'required' => true,
'first_options' => [
'label' => 'oro.user.password.label',
'tooltip' => $this->optionsProvider->getTooltip(),
'attr' => [
'data-validation' => $this->optionsProvider->getDataValidationOption()
]
],
'second_options' => [
'label' => 'oro.user.password_re.label',
],
]
)
->add(
'emails',
'collection',
[
'label' => 'oro.user.emails.label',
'type' => 'oro_user_email',
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'prototype' => true,
'prototype_name' => 'tag__name__'
]
)
->add('change_password', ChangePasswordType::NAME)
->add('avatar', 'oro_image', ['label' => 'oro.user.avatar.label', 'required' => false]);
$this->addInviteUserField($builder);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(
[
'data_class' => 'Oro\Bundle\UserBundle\Entity\User',
'intention' => 'user',
'validation_groups' => function ($form) {
if ($form instanceof FormInterface) {
$user = $form->getData();
} elseif ($form instanceof FormView) {
$user = $form->vars['value'];
} else {
$user = null;
}
return $user && $user->getId()
? ['Roles', 'Default']
: ['Registration', 'Roles', 'Default'];
},
'ownership_disabled' => $this->isMyProfilePage
]
);
}
/**
* {#inheritdoc}
*/
public function getName()
{
return $this->getBlockPrefix();
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'oro_user_user';
}
/**
* Set user fields
*
* #param FormBuilderInterface $builder
*/
protected function setDefaultUserFields(FormBuilderInterface $builder)
{
$builder
->add('username', 'text', ['label' => 'oro.user.username.label', 'required' => true])
->add('email', 'email', ['label' => 'oro.user.email.label', 'required' => true])
->add('phone', 'text', ['label' => 'oro.user.phone.label', 'required' => false])
->add('namePrefix', 'text', ['label' => 'oro.user.name_prefix.label', 'required' => false])
->add('firstName', 'text', ['label' => 'oro.user.first_name.label', 'required' => true])
->add('middleName', 'text', ['label' => 'oro.user.middle_name.label', 'required' => false])
->add('lastName', 'text', ['label' => 'oro.user.last_name.label', 'required' => true])
->add('nameSuffix', 'text', ['label' => 'oro.user.name_suffix.label', 'required' => false])
->add('birthday', OroBirthdayType::class, ['label' => 'oro.user.birthday.label', 'required' => false]);
}
/**
* Add Invite user fields
*
* #param FormBuilderInterface $builder
*/
protected function addInviteUserField(FormBuilderInterface $builder)
{
$builder->add(
'inviteUser',
'checkbox',
[
'label' => 'oro.user.invite.label',
'mapped' => false,
'required' => false,
'tooltip' => 'oro.user.invite.tooltip',
'data' => true
]
);
}
/**
* #param FormBuilderInterface $builder
*/
protected function addOrganizationField(FormBuilderInterface $builder)
{
if ($this->securityFacade->isGranted('oro_organization_view')
&& $this->securityFacade->isGranted('oro_business_unit_view')
) {
$builder->add(
'organizations',
'oro_organizations_select',
[
'required' => false,
]
);
}
}
... /Entity/User.php
<?php
namespace Oro\Bundle\UserBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Event\PreUpdateEventArgs;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as JMS;
use Oro\Bundle\EmailBundle\Entity\EmailOrigin;
use Oro\Bundle\EmailBundle\Entity\EmailOwnerInterface;
use Oro\Bundle\EmailBundle\Model\EmailHolderInterface;
use Oro\Bundle\EntityConfigBundle\Metadata\Annotation\Config;
use Oro\Bundle\EntityConfigBundle\Metadata\Annotation\ConfigField;
use Oro\Bundle\ImapBundle\Entity\UserEmailOrigin;
use Oro\Bundle\ImapBundle\Form\Model\AccountTypeModel;
use Oro\Bundle\LocaleBundle\Model\FullNameInterface;
use Oro\Bundle\NotificationBundle\Entity\NotificationEmailInterface;
use Oro\Bundle\OrganizationBundle\Entity\BusinessUnit;
use Oro\Bundle\OrganizationBundle\Entity\Organization;
use Oro\Bundle\OrganizationBundle\Entity\OrganizationInterface;
use Oro\Bundle\UserBundle\Model\ExtendUser;
use Oro\Bundle\UserBundle\Security\AdvancedApiUserInterface;
/**
* #SuppressWarnings(PHPMD.ExcessivePublicCount)
* #SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* #SuppressWarnings(PHPMD.ExcessiveClassLength)
*
* #ORM\Entity(repositoryClass="Oro\Bundle\UserBundle\Entity\Repository\UserRepository")
* #ORM\Table(name="oro_user", indexes = {
* #ORM\Index("user_first_name_last_name_idx", columns = {"first_name", "last_name"})
* })
* #ORM\HasLifecycleCallbacks()
* #Config(
* routeName="oro_user_index",
* routeView="oro_user_view",
* defaultValues={
* "entity"={
* "icon"="fa-user"
* },
* "grouping"={
* "groups"={"dictionary"}
* },
* "dictionary"={
* "virtual_fields"={"id"},
* "search_fields"={"firstName", "lastName"},
* "representation_field"="fullName",
* "activity_support"="true"
* },
* "ownership"={
* "owner_type"="BUSINESS_UNIT",
* "owner_field_name"="owner",
* "owner_column_name"="business_unit_owner_id",
* "organization_field_name"="organization",
* "organization_column_name"="organization_id"
* },
* "dataaudit"={"auditable"=true},
* "security"={
* "type"="ACL",
* "group_name"="",
* "category"="account_management"
* },
* "form"={
* "form_type"="oro_user_select",
* "grid_name"="users-select-grid"
* },
* "grid"={
* "default"="users-grid",
* "context"="users-for-context-grid"
* },
* "tag"={
* "enabled"=true
* }
* }
* )
* #JMS\ExclusionPolicy("ALL")
*/
class User extends ExtendUser implements
EmailOwnerInterface,
EmailHolderInterface,
FullNameInterface,
NotificationEmailInterface,
OrganizationAwareUserInterface,
AdvancedApiUserInterface
{
const ROLE_DEFAULT = 'ROLE_USER';
const ROLE_ADMINISTRATOR = 'ROLE_ADMINISTRATOR';
const ROLE_ANONYMOUS = 'IS_AUTHENTICATED_ANONYMOUSLY';
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #JMS\Type("integer")
* #JMS\Expose
*/
protected $id;
/**
* #var string
*
* #ORM\Column(type="string", length=255, unique=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* },
* "importexport"={
* "identity"=true
* }
* }
* )
*/
protected $username;
/**
* #var string
*
* #ORM\Column(type="string", length=255, unique=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $email;
/**
* Name prefix
*
* #var string
*
* #ORM\Column(name="name_prefix", type="string", length=255, nullable=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $namePrefix;
/**
* First name
*
* #var string
*
* #ORM\Column(name="first_name", type="string", length=255, nullable=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $firstName;
/**
* Middle name
*
* #var string
*
* #ORM\Column(name="middle_name", type="string", length=255, nullable=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $middleName;
/**
* Last name
*
* #var string
*
* #ORM\Column(name="last_name", type="string", length=255, nullable=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $lastName;
/**
* Name suffix
*
* #var string
*
* #ORM\Column(name="name_suffix", type="string", length=255, nullable=true)
* #JMS\Type("string")
* #JMS\Expose
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
protected $nameSuffix;
/**
* #var Group[]|Collection
*
* #ORM\ManyToMany(targetEntity="Oro\Bundle\UserBundle\Entity\Group")
* #ORM\JoinTable(name="oro_user_access_group",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(name="group_id", referencedColumnName="id", onDelete="CASCADE")}
* )
* #ConfigField(
* defaultValues={
* "dataaudit"={
* "auditable"=true
* }
* }
* )
*/
(...)
You can inherit the UserBundle and override the parts you need.
Symfony docs for bundle inheritance.
I'm learning by myself the symfony framework (my job is not about developing, I'm not a developer) and I find out most of case the solution but here, is one what I didn't know how to manage.
I have 2 entity :
Product:
/**
* Product
*
* #ORM\Table(name="product")
* #ORM\Entity(repositoryClass="ProductBundle\Repository\ProductRepository")
* #UniqueEntity("productNumber")
*/
class Product
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="productNumber", type="string", length=255, unique=true)
* #Assert\Regex(
* pattern="/[0-9][.][0-9]{3}/",
* message="It should be like 1.234"
* )
*/
private $productNumber;
/**
* #ORM\ManyToOne(targetEntity="ProductGroup")
*/
private $productGroup;
/**
* Constructor
*/
public function __construct()
{
}
}
Camera :
/**
* Camera
*
* #ORM\Table(name="camera")
* #ORM\Entity(repositoryClass="ProductBundle\Repository\CameraRepository")
*/
class Camera
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="modele", type="string", length=255, unique=true)
*/
private $modele;
/**
* #var string
*
* #ORM\Column(name="description", type="text")
*/
private $description;
/**
*
* #ORM\ManyToOne(targetEntity="Product")
*/
private $product;
/**
* #ORM\ManyToMany(targetEntity="CustomField", inversedBy="camera", cascade={"persist", "remove"}, orphanRemoval=true)
*/
protected $customFields;
/**
* Constructor
*/
public function __construct()
{
$this->customFields = new ArrayCollection();
}
}
My form :
namespace ProductBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class CameraType extends AbstractType {
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('product', EntityType::class, [
'class' => 'ProductBundle:Product',
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('p')
->select('p')
->leftJoin('ProductBundle:Camera', 'c', 'WITH', 'c.product = p.id')
->where('c.product IS NULL')
;
},
'attr' => [
'required' => true,
],
'choice_label' => 'productNumber',
])
->add('modele', TextType::class, [
'label' => "Modele",
])
->add('description', TextType::class, [
'label' => "Description",
])
->add('customFields', CollectionType::class, [
'entry_type' => CustomFieldType::class,
'allow_add' => true,
'allow_delete' => true,
'prototype' => true,
'required' => false,
'attr' => [
'class' => 'customfield'
]
])
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'ProductBundle\Entity\Camera'
));
}
}
When I add a camera, I would like only the Product:productNumber where are available (not take by a camera), the querybuilder is working but my issue concern the edit form, it show only available productNumber so it's changing every time I need to edit this camera.
What can I handle this ? Should I try to found another way to add a productNumber ? do you have a "trick" ?
I hope you will understand the problem and my english because it's not my first language.
Have a nice day.
Edit : I'm on Symfony 3.1.4
I presume on new form your choice field shows only unused ProductBundle:Camera entity, and on edit form it should show saved ProductBundle:Camera entity and all unused ones.
You should look into Form Event Subscribers
You need to implement two event listeners PRE_SET_DATA and PRE_SUBMIT.
Here is one way to do it. Something like this works on SF 2.8
First you will have to create product entity form from custom ProductFieldSubscriber which becomes EventSubscriberInterface:
$builder->addEventSubscriber(new ProductFieldSubscriber('product', [])
Now ProductFieldSubscriber should look something like this (untested)
namespace ProductBundle\Form\EventListener;
use Symfony\Component\Form\FormInterface,
Symfony\Component\Form\FormEvent,
Symfony\Component\EventDispatcher\EventSubscriberInterface,
Symfony\Component\Form\FormEvents,
Doctrine\ORM\EntityRepository,
Symfony\Bridge\Doctrine\Form\Type as DoctrineTypes
;
class ProductFieldSubscriber implements EventSubscriberInterface
{
private $propertyPathToSelf;
public function __construct($propertyPathToSelf, array $formOptions=[]) {
$this->propertyPathToSelf = $propertyPathToSelf;
$this->formOptions = $formOptions;
}
public static function getSubscribedEvents() {
return [
FormEvents::PRE_SET_DATA => 'onPreSetData',
FormEvents::PRE_SUBMIT => 'onPreSubmit',
];
}
private function addForm(FormInterface $form, $selfId = null) {
$formOptions = array_replace_recursive ([
'class' => 'ProductBundle:Product',
'placeholder' => null,
'compound' => false,
'query_builder' => function (EntityRepository $er) use ($selfId) {
$qb = $er->createQueryBuilder('p')
->select('p')
->leftJoin('ProductBundle:Camera', 'c', 'WITH', 'c.product = p.id')
->where('c.product IS NULL')
;
if (null !== $selfId) {
$qb
->orWhere($qb->expr()->eq('p.product', ':existingId'))
->setParameter('existingId', $selfId->getId())
;
}
return $qb;
},
],
$this->formOptions
);
if ($selfId) {
$formOptions['data'] = $selfId;
}
$form->add($this->propertyPathToSelf, DoctrineTypes\EntityType::class, $formOptions);
}
public function onPreSetData(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (null === $data) {
return;
}
$selfIdTypeMethod = "get{$this->propertyPathToSelf}";
$selfId = $data->$selfIdTypeMethod();
$this->addForm($form, $selfId);
}
public function onPreSubmit(FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
$selfId = array_key_exists($this->propertyPathToSelf, $data) ? $data[$this->propertyPathToSelf] : null;
$this->addForm($form, $selfId);
}
}
Query builder would be simpler if you had mapped entity relations.
Bonus update:
form option 'placeholder' => null, takes care that no default 'empty' option is available.
form option 'required' => true, forces html5 form popup validation.
Then you should use something like entity #assert notations and use validator constraints on entity attribute:
use Symfony\Component\Validator\Constraints as Assert;
/**
* #var string
*
* #Assert\NotNull()
* #ORM\Column(name="modele", type="string", length=255, unique=true)
*/
private $modele;
You could also disallow edit form from opening via controller editAction (maybe some redirect) and twig, where you could hide edit button.
I'm receiving this error on Symfony 2.7.9:
Neither the property "puestos" nor one of the methods "addPuesto()"/"removePuesto()", "setPuestos()", "puestos()", "__set()" or "__call()" exist and have public access in class "UserBundle\Entity\UsuarioTrabajador".
<?php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use PUGX\MultiUserBundle\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #ORM\Table(name="usuario_trabajador")
* #UniqueEntity(fields = "username", targetClass = "UserBundle\Entity\Usuario", message="fos_user.username.already_used")
* #UniqueEntity(fields = "email", targetClass = "UserBundle\Entity\Usuario", message="fos_user.email.already_used")
*
* #UniqueEntity(fields = {"nit","dpi"}, targetClass = "UserBundle\Entity\UsuarioTrabajador", message="El dpi o nit debe ser único")
* Esta entidad cubre los tipos de Asistente, Supervisor y Gerente.
*
* #author Pablo Díaz soporte#newtonlabs.com.gt
*/
class UsuarioTrabajador extends Usuario
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(name="direccion",type="string",length=255)
*/
private $direccion;
/**
* #var date fecha de egreso de la empresa.
* #ORM\Column(name="fechaEgreso", type="date",nullable=true)
*/
private $fechaEgreso;
/**
* #var string DPI del trabajador
* #ORM\Column(name="dpi",type="string",length=20, unique=true)
*/
private $dpi;
/**
* Número de identificación tributaria.
*
* #var string
* #ORM\Column(name="nit", type="string",length=20,unique=true)
*/
private $nit;
/**
* #var int
* #ORM\Column(name="telefono", type="string",length=15,nullable=true)
*/
private $telefono;
/**
* #var ArrayCollection
* #ORM\OneToMany(targetEntity="DatosPrestaciones", mappedBy="usuario")
*/
private $datosPrestaciones;
/**
* #var string Tipo de Usuarios(Asistente, Supervisor, Gerente)
* #ORM\OneToMany(targetEntity="UserBundle\Entity\Puesto", mappedBy="usuarioPuesto")
*/
private $puestos;
/**
* Constructor.
*/
public function __construct()
{
$this->datosPrestaciones = new \Doctrine\Common\Collections\ArrayCollection();
$this->puestos = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Set direccion
*
* #param string $direccion
*
* #return UsuarioTrabajador
*/
public function setDireccion($direccion)
{
$this->direccion = $direccion;
return $this;
}
/**
* Get direccion
*
* #return string
*/
public function getDireccion()
{
return $this->direccion;
}
/**
* Set fechaEgreso
*
* #param \DateTime $fechaEgreso
*
* #return UsuarioTrabajador
*/
public function setFechaEgreso($fechaEgreso)
{
$this->fechaEgreso = $fechaEgreso;
return $this;
}
/**
* Get fechaEgreso
*
* #return \DateTime
*/
public function getFechaEgreso()
{
return $this->fechaEgreso;
}
/**
* Set dpi
*
* #param string $dpi
*
* #return UsuarioTrabajador
*/
public function setDpi($dpi)
{
$this->dpi = $dpi;
return $this;
}
/**
* Get dpi
*
* #return string
*/
public function getDpi()
{
return $this->dpi;
}
/**
* Set nit
*
* #param string $nit
*
* #return UsuarioTrabajador
*/
public function setNit($nit)
{
$this->nit = $nit;
return $this;
}
/**
* Get nit
*
* #return string
*/
public function getNit()
{
return $this->nit;
}
/**
* Set telefono
*
* #param string $telefono
*
* #return UsuarioTrabajador
*/
public function setTelefono($telefono)
{
$this->telefono = $telefono;
return $this;
}
/**
* Get telefono
*
* #return string
*/
public function getTelefono()
{
return $this->telefono;
}
/**
* Add datosPrestacione
*
* #param \UserBundle\Entity\DatosPrestaciones $datosPrestacione
*
* #return UsuarioTrabajador
*/
public function addDatosPrestacione(\UserBundle\Entity\DatosPrestaciones $datosPrestacione)
{
$this->datosPrestaciones[] = $datosPrestacione;
return $this;
}
/**
* Remove datosPrestacione
*
* #param \UserBundle\Entity\DatosPrestaciones $datosPrestacione
*/
public function removeDatosPrestacione(\UserBundle\Entity\DatosPrestaciones $datosPrestacione)
{
$this->datosPrestaciones->removeElement($datosPrestacione);
}
/**
* Get datosPrestaciones
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getDatosPrestaciones()
{
return $this->datosPrestaciones;
}
/**
* Add puesto
*
* #param \UserBundle\Entity\Puesto $puesto
*
* #return UsuarioTrabajador
*/
public function addPuesto(\UserBundle\Entity\Puesto $puesto)
{
$this->puestos[] = $puesto;
return $this;
}
/**
* Remove puesto
*
* #param \UserBundle\Entity\Puesto $puesto
*/
public function removePuesto(\UserBundle\Entity\Puesto $puesto)
{
$this->puestos->removeElement($puesto);
}
/**
* Get puestos
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getPuestos()
{
return $this->puestos;
}
public function __toString()
{
return $this->nombre.' '.$this->apellidos;
}
}
This is the other Entity
<?php
namespace UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Puesto
*
* #ORM\Table()
* #ORM\Entity
*/
class Puesto
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="tipoPuesto",type="string",length=100)
*/
private $tipoPuesto;
/**
* #var string
*
* #ORM\Column(name="nombrePuesto", type="string", length=255)
*/
private $nombrePuesto;
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="date")
*/
private $date;
/**
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\UsuarioTrabajador", inversedBy="puestos")
* #var [type]
*/
private $usuarioPuesto;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set nombrePuesto
*
* #param string $nombrePuesto
*
* #return Puesto
*/
public function setNombrePuesto($nombrePuesto)
{
$this->nombrePuesto = $nombrePuesto;
return $this;
}
/**
* Get nombrePuesto
*
* #return string
*/
public function getNombrePuesto()
{
return $this->nombrePuesto;
}
/**
* Set date
*
* #param \DateTime $date
*
* #return Puesto
*/
public function setDate($date)
{
$this->date = $date;
return $this;
}
/**
* Get date
*
* #return \DateTime
*/
public function getDate()
{
return $this->date;
}
/**
* Set usuario
*
* #param \UserBundle\Entity\UsuarioTrabajdor $usuario
*
* #return Puesto
*/
public function setUsuario(\UserBundle\Entity\UsuarioTrabajdor $usuario = null)
{
$this->usuario = $usuario;
return $this;
}
/**
* Get usuario
*
* #return \UserBundle\Entity\UsuarioTrabajdor
*/
public function getUsuario()
{
return $this->usuario;
}
/**
* Set tipoPuesto
*
* #param string $tipoPuesto
*
* #return Puesto
*/
public function setTipoPuesto($tipoPuesto)
{
$this->tipoPuesto = $tipoPuesto;
return $this;
}
/**
* Get tipoPuesto
*
* #return string
*/
public function getTipoPuesto()
{
return $this->tipoPuesto;
}
/**
* Mostrar el noombre del puesto
* #return string
*/
public function __toString()
{
return $this->tipoPuesto.': '.$this->nombrePuesto.' '.$this->getUsuarioPuesto();
}
/**
* Set usuarioPuesto
*
* #param \UserBundle\Entity\UsuarioTrabajador $usuarioPuesto
*
* #return Puesto
*/
public function setUsuarioPuesto(\UserBundle\Entity\UsuarioTrabajador $usuarioPuesto = null)
{
$this->usuarioPuesto = $usuarioPuesto;
return $this;
}
/**
* Get usuarioPuesto
*
* #return \UserBundle\Entity\UsuarioTrabajador
*/
public function getUsuarioPuesto()
{
return $this->usuarioPuesto;
}
}
This is the Form
<?php
namespace UserBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class RegistrationTrabajadorFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
// agregar campos personalizados
$builder->add('nombre', null, [
'label' => 'Nombre/s',
'attr' => [
'placeholder' => 'Nombre/s',
'class' => 'form-control input-lg',
],
])
->add('apellidos', null, [
'label' => 'Apellidos/s',
'attr' => [
'placeholder' => 'Apellidos',
'class' => 'form-control input-lg',
],
])
->add('username', null, [
'label' => 'Usuario',
'translation_domain' => 'FOSUserBundle',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Nombre de Usuario',
],
])
->add('email', 'email', [
'label' => 'Correo',
'translation_domain' => 'FOSUserBundle',
'required' => true,
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Correo electrónico',
],
])
->add('plainPassword', 'repeated', [
'label' => 'Contraseña',
'type' => 'password',
'options' => ['translation_domain' => 'FOSUserBundle'],
'first_options' => [
'label' => 'Contraseña',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Contraseña',
],
],
'second_options' => [
'label' => 'Repetir Contraseña',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Repetir Contraseña',
],
],
'invalid_message' => 'fos_user.password.mismatch',
])
->add('direccion',null,[
'label' => 'Dirección',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Dirección',
],
'required' => true,
])
->add('dpi', null, [
'label' => 'DPI',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Documento Personal de Identificación',
],
'required' => true,
])
->add('nit', null, [
'label' => 'NIT',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Número de Identificación Tributaria',
],
'required' => true,
])
->add('telefono', null, [
'label' => 'Teléfono',
'translation_domain' => 'FOSUserBundle',
'attr' => [
'class' => 'form-control input-lg',
'placeholder' => 'Teléfono',
],
'required' => false,
])
->add('submit', 'submit', [
'label' => 'Guardar',
'attr' => [
'class' => 'btn btn-primary',
],
])
->add('puestos', 'entity', [
'label' => false,
'empty_value' => 'Aquí aparecerá su puesto',
'class' => 'UserBundle:Puesto',
'attr' => [
'class' => 'select2',
],
])
;
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'validation' => ['registration'],
]);
}
public function getParent()
{
return 'fos_user_registration';
}
public function getName()
{
return 'user_registration';
}
}
I am overriding the form type to register a user. All looks ok, but when I submit my form the new fields are not persisted in database.
I followed the documentation.
My ProfileType:
<?php
namespace Application\Sonata\UserBundle\Form\Type;
//use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
//use Sonata\UserBundle\Model\UserInterface;
use Sonata\UserBundle\Form\Type\ProfileType as BaseType;
class ProfileType extends BaseType
{
private $class;
/**
* #param string $class The User class name
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {#inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
parent::buildForm($builder, $options);
$builder
->add('username', null, array(
'label' => 'Pseudo',
'required' => false
))
->add('firstname', null, array(
'label' => 'Prénom'
))
->add('lastname', null, array(
'label' => 'Nom'
))
->add('email', 'email', array(
'label' => 'Email'
))
->add('dateOfBirth', 'birthday', array(
'label' => 'Date d\'anniversaire',
'required' => false,
'data' => new \DateTime("01/01/1980")
))
->add('plainPassword', 'password', array(
'label' => 'Password'
))
->add('phone', null, array(
'label' => 'Téléphone',
'required' => false
))
->add('adress', null, array(
'label' => 'Adresse',
'required' => false
))
->add('zip', null, array(
'label' => 'Code postale',
'required' => false
))
->add('city', null, array(
'label' => 'Ville',
'required' => false
))
->add('newsletter', 'checkbox', array(
'label' => 'newsletter',
'required' => false
))
#hidden
->add('website', 'hidden', array(
'label' => 'website',
'required' => false
))
->add('biography', 'hidden', array(
'label' => 'biography',
'required' => false
))
->add('locale', 'hidden', array(
'label' => 'locale',
'required' => false
))
->add('timezone', 'hidden', array(
'label' => 'Timezone',
'required' => false
))
->add('gender', 'hidden', array(
'label' => 'Civilité',
'required' => false
))
;
// var_dump($builder);
}
/**
* {#inheritdoc}
*/
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Application\Sonata\UserBundle\Entity\User',
'intention' => 'profile',
'label' => 'Edit Profile'
));
}
// public function getParent()
// {
// return 'fos_user_registration';
// }
/**
* {#inheritdoc}
*/
public function getName()
{
return 'application_sonata_user_profile';
}
}
My user class:
<?php
namespace Application\Sonata\UserBundle\Entity;
use Sonata\UserBundle\Entity\BaseUser as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
/**
* Application\Sonata\UserBundle\Entity\User
*
* #ORM\Table(name="fos_user_user", indexes={#ORM\Index(name="search_idx", columns={"username", "email"})}))
* #ORM\Entity()
* #DoctrineAssert\UniqueEntity(fields={"username"}, message="username.already.exist" )
* #DoctrineAssert\UniqueEntity(fields={"email"}, message="email.already.exist" )
*/
class User extends BaseUser
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="zip", type="string", length=255, nullable=true)
*/
protected $zip;
/**
* #var string
*
* #ORM\Column(name="adress", type="text", nullable=true)
*/
protected $adress;
/**
* #var string
*
* #ORM\Column(name="city", type="string", length=255, nullable=true)
*/
protected $city;
/**
* #var boolean
*
* #ORM\Column(name="newsletter", type="boolean", nullable=true)
*/
private $newsletter;
/**
* Get id
*
* #return integer $id
*/
public function getId()
{
return $this->id;
}
/**
* Set zip
*
* #param string $zip
* #return FosUserUser
*/
public function setZip($zip)
{
$this->zip = $zip;
return $this;
}
/**
* Get zip
*
* #return string
*/
public function getZip()
{
return $this->zip;
}
/**
* Set adress
*
* #param string $adress
* #return FosUserUser
*/
public function setAdress($adress)
{
$this->adress = $adress;
return $this;
}
/**
* Get adress
*
* #return string
*/
public function getAdress()
{
return $this->adress;
}
/**
* Set city
*
* #param string $city
* #return FosUserUser
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* #return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set Newsletter
*
* #param boolean $newsletter
* #return FosUserUser
*/
public function setNewsletter($newsletter)
{
$this->newsletter = $newsletter;
return $this;
}
/**
* Get Newsletter
*
* #return boolean
*/
public function getNewsletter()
{
return $this->newsletter;
}
}
Thank you for your help.
If you have a just created properties of the entity and you are using the metadata cache, the doctrine still doesn't aware about these new properties. Just try to clear the metadata cache.