Symfony:创建新用户会导致覆盖属性

时间:2017-12-15 13:47:36

标签: symfony entity fosuserbundle

两天后,当有人在我们的应用程序上创建新用户时,他自己的一些属性会被新用户属性覆盖。 我还没有任何线索,在哪里寻找错误,因为在控制器或实体中,没有任何改变。

以下是一些信息: 用户实体(我们正在使用FOS用户包)

class User extends BaseUser{

        /**
         * @Solr\Id
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;

        /**
         * @Solr\Field(type="string")
         * @Assert\NotBlank()
         * @var string
         * @ORM\Column(type="string", length=32, nullable=false)
         */
        protected $firstName;

        /**
         * @Solr\Field(type="string")
         * @Assert\NotBlank()
         * @var string
         * @ORM\Column(type="string", length=32, nullable=false)
         */
        protected $lastName;

        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Agency", inversedBy="useragencies", cascade={"persist"})
         * @ORM\JoinTable(name="user_user_agencies",
         *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *   inverseJoinColumns={@ORM\JoinColumn(name="iata8", referencedColumnName="iata8")})
         * @var \AppBundle\Entity\Agency
         **/
        private $agencies;

        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Product", inversedBy="users", cascade={"persist"})
         * @ORM\JoinTable(name="user_user_products",
         *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *   inverseJoinColumns={@ORM\JoinColumn(name="product_id", referencedColumnName="id")})
         * @var \AppBundle\Entity\Product
         **/
        private $products;

        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Market", inversedBy="users", cascade={"persist"})
         * @ORM\JoinTable(name="user_user_markets",
         *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *   inverseJoinColumns={@ORM\JoinColumn(name="market_id", referencedColumnName="id")})
         * @var \AppBundle\Entity\Market
         * @Solr\Field(type="string", getter="getId")
         **/
        private $markets;

        /**
         * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Airline", inversedBy="users", cascade={"persist"})
         * @ORM\JoinTable(name="user_user_airlines",
         *   joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
         *   inverseJoinColumns={@ORM\JoinColumn(name="airline_id", referencedColumnName="id")})
         * @var \AppBundle\Entity\Airline
         * @Solr\Field(type="string", getter="getId")
         **/
        private $airlines;
...

被覆盖的属性是产品航空公司 此实体没有prePersist()或preUpdate()函数!

创建控制器

    class CreateController extends Controller
{

  /**
   * @Security("has_role('ROLE_USER_INVITER')")
   * @Route("/user/create/{employer}", defaults={"employer": 1}
   *     , requirements={"employer": "\d+"}, name="userBundle_create")
   */
  public function createAction($employer, Request $request)
  {
      $currentUser=$this->container->get('security.token_storage')->getToken()->getUser();

      // get employer Object
      $em = $this->getDoctrine ()->getManager ();
      $repository = $this->getDoctrine()
      ->getRepository('UserBundle:Employer');

      $employerObj = $repository->findOneByIdInContext($employer, $currentUser);

      $userManager = $this->get('fos_user.user_manager');

      $user = $userManager->createUser();
      $url = $this->get('router')->generate('userBundle_create', array(
            'employer' => $employerObj->getId()
        ));

      // generate form and handle
      $form = $this->createForm(CreateType::class, $user
        , array('employer' => $employerObj,
                'action' => $url,)
        );
      $form->handleRequest($request);

      if ($form->isValid()) {

          $tokenGenerator = $this->container->get('fos_user.util.token_generator');
          $user->setConfirmationToken($tokenGenerator->generateToken());
          $user->setUsername($user->getEmail());
          $user->setEnabled(false);
          $user->setApprover($currentUser);
          $user->setInviter($currentUser);
          $user->addRole($user->getMainRole()->getName());

          $userManager->updateUser($user);
           if(count($user->getAgencies()) > 0){
            $userId = rtrim($user->getId(),"_user");

            $query = $em->createQuery("SELECT DISTINCT (a.market) FROM UserBundle\Entity\User u JOIN u.agencies a WHERE u.id = $userId");
            $marketIds = $query->getResult();

            $em = $this->getDoctrine ()->getManager ();
            $repository = $this->getDoctrine()
            ->getRepository('AppBundle:Market');

            $markets = $repository->findOneById($marketIds[0]);
            $user->addMarket($markets);
            $userManager->updateUser($user);
          }

          $this->addFlash(
              'success',
              'The user was created and an activation email was sent!'
          );

          return $this->redirectToRoute('userBundle_list');

      }

      return $this->render('UserBundle:User:create.html.twig', array(
        'form' => $form->createView(),
        'user'=>$user,
      ));

  }

}

我不知道哪些类可能对帮助我指向正确的方向有用。我明白,你们中的任何一个人都很难解决这个问题,但也许有人已经经历过类似的事情,可以通过告诉我在哪里可以帮助我。

谢谢!

CreateType

    class CreateType extends AbstractType
{

    private $tokenStorage;

    public function __construct(TokenStorageInterface $tokenStorage)
    {
        $this->tokenStorage = $tokenStorage;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => User::class,
            'employer' => null
        ));
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {


        $employer = $options['employer'];

        $builder

        ->add('firstName', 'text', array('label' => 'label.firstname',
          'translation_domain' => 'User',))

        ->add('lastName', 'text', array('label' => 'label.lastname',
          'translation_domain' => 'User',))

        ;

        $user = $this->tokenStorage->getToken()->getUser();

        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($user, $employer){
          $form = $event->getForm();

          // show iata selection if empoyer is any agency
          $employerArr = array(10, 11);
          if (in_array($employer->getId(), $employerArr)) {
            // only show iata based on user's employer
            if($user->hasRoles(array('ROLE_AGENCY_TC_ONLY',
              'ROLE_AGENCY_WAIVER_REQUEST_ONLY',
              'ROLE_AGENCY_CORE_TEAM',
              'ROLE_AGENCY',
              'ROLE_AGENCY_MANAGEMENT',
              'ROLE_AGENCY_SIGNEE','ROLE_CORPORATION_TRAVEL_MANAGER' ))){

                $form

                ->add('agencies', EntityType::class, array(
                 'class' => 'AppBundle:Agency',
                 'query_builder' => function (EntityRepository $er) use ($user) {
                 return $er->createQueryBuilder('a')
                 ->addOrderBy('a.id', 'ASC')
                 ->andWhere('a.id IN (:ids)')
                 ->setParameter('ids',$user->getAgencies());
                 },
                 'choice_label' => 'agencyName',
                //  'data' => $user->getAgencies(),
                 'label' => 'label.iata',
                 'empty_value' => "label.select.agency",
                 'property' => 'id',
                 'expanded' => false, 'multiple' => true,
                 'required' => true,
                 'translation_domain' => 'User',
                 'choice_translation_domain' => 'User'));
             }  else {
               // only show iata based on user's context
               $form
                     ->add('agencies', EntityType::class, array(
                        'class' => 'AppBundle:Agency',
                        'query_builder' => function (EntityRepository $er) use ($user) {
                        return $er->createQueryBuilder('a')
                        ->addOrderBy('a.id', 'ASC')
                        ->andWhere('a.market IN (:markets)')
                        ->setParameter('markets',$user->getMarkets());
                        },
                        'choice_label' => 'agencyName',
                        'label' => 'label.iata',
                        'empty_value' => "label.select.agency",
                        'property' => 'id',
                        'expanded' => false, 'multiple' => true,
                        'required' => true,
                        'translation_domain' => 'User',
                        'choice_translation_domain' => 'User'));
                }
          // show market only if not agency user
          } else {

          // only show specific markets based on user's context

          $form->add('markets', 'entity', array(
            'class' => 'AppBundle:Market', 'property' => 'id',
            'query_builder' => function (EntityRepository $er) use ($user) {
              $markets = $user->getMarkets();

              return $er->createQueryBuilder('m')
                ->addOrderBy('m.id', 'ASC')
                ->andWhere('m.id IN (?1)')
                ->setParameter(1,$markets);
              },
            // 'choice_value' => 'id',
            'choice_label' => 'id', 'label' => 'label.markets',
            'translation_domain' => 'User',
            'expanded' => false, 'multiple' => true,));

          }


          // only show specific roles based on user's employer

          $form->add('mainRole', 'entity', array(
              'class' => 'UserBundle:Role',
              'query_builder' => function (EntityRepository $er) use ($employer){
                  $roles = $employer->getRoles();
                  return $er->createQueryBuilder('r')
                      ->orderBy('r.sort', 'ASC')
                      ->andWhere('r.id IN (?1)')
                      ->setParameter(1,$roles);
              },
              'choice_label' => 'translationKey',
              'choices_as_values' => true, 'label' => 'label.role',
              'expanded' => true, 'multiple' => false,
              'translation_domain' => 'User',
              'choice_translation_domain' => 'Role',));

              // only show specific airlines based on user's context

              $form->add('airlines', 'entity', array(
                'class' => 'AppBundle:Airline', 'property' => 'id',
                'query_builder' => function (EntityRepository $er) use ($user) {
                  $airlines = $user->getAirlines();

                  return $er->createQueryBuilder('a')
                    ->addOrderBy('a.id', 'ASC')
                    ->andWhere('a.id IN (?1)')
                    ->setParameter(1,$airlines);
                  },
                'choice_value' => 'id',
                'data' => $user->getAirlines(),
                'choice_label' => 'id', 'label' => 'label.airlines',
                'translation_domain' => 'User',
                'expanded' => false, 'multiple' => true,));

                // only show specific products based on user's context

              $form->add('products', 'entity', array(
                'class' => 'AppBundle:Product', 'property' => 'id',
                'query_builder' => function (EntityRepository $er) use ($user) {
                  $products = $user->getProducts();

                  return $er->createQueryBuilder('p')
                    ->addOrderBy('p.id', 'ASC')
                    ->andWhere('p.id IN (?1)')
                    ->setParameter(1,$products);
                  },
                'choice_value' => 'id',
                'data' => $user->getProducts(),
                'choice_label' => 'translationKey', 'label' => 'label.products',
                'translation_domain' => 'User',
                'expanded' => false, 'multiple' => true,
                'choice_translation_domain' => 'AppBundle',));
          });

    }

    public function getParent()
    {
        return 'FOS\UserBundle\Form\Type\RegistrationFormType';

    }



    public function getBlockPrefix()
    {
        return 'userBundle_create';
    }

}

1 个答案:

答案 0 :(得分:0)

你的问题是由这些线引起的:

'data' => $user->getAirlines(),

'data' => $user->getProducts(),

更改新用户s airlines & products collection, symfony form uses the loggedin user的航空公司&产品系列参考

在将集合设置为默认值时克隆集合,以删除对登录用户的引用。

'data' => clone $user->getAirlines(),

'data' => clone $user->getProducts(),

希望它有所帮助。

错误的假设 :您的错误位于 CreateType 类中。您可以使用已登录用户的属性填充表单中的代理商航空公司产品字段:

$user = $this->tokenStorage->getToken()->getUser();
...
'query_builder' => function (EntityRepository $er) use ($user) {

您应该使用您编辑的用户。添加 buildForm 功能:

$userEdited = $builder->getData();

然后改变:

'query_builder' => function (EntityRepository $er) use ($userEdited) {

在所有地方。

别忘了改变:

$user->getMarkets()

$userEdited->getMarkets()

在你的回调中,同样对于ailines&产品