Форма Symfony для хранения выбора пользовательских интересов в пользовательских интересах - PullRequest
2 голосов
/ 04 июля 2019

Моя цель - использовать форму Symfony, чтобы позволить пользователю выбрать несколько интересов и сохранить их по отношению к своему пользователю.

У меня есть три объекта для сопоставления и хранения этих данных:

User
 - id
 - name

Interest
 - id
 - name

UserInterest
 - id
 - user_id (FK ManyToOne user.id)
 - interest_id (FK ManyToOne interest.id)

Я изо всех сил пытаюсь найти наиболее динамичный Symfony способ обработки и сохранения Interest s User в UserInterest сущности.

InterestsController.php

public function interests(Request $request)
{
    $error = null;

    $userInterests = new UserInterest();
    $userInterests->setUser($this->getUser());

    $form = $this->createForm(UserAccountInterests::class, $userInterests);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        try {
            $this->entityManager->persist($userInterests);
            $this->entityManager->flush();
    } catch (\Exception $e) {
            $error = $e->getMessage();
        }
    }

    $parameters = [
        'error' => $error,
        'user_interests_form' => $form->createView()
    ];

    return $this->render('user/interests.html.twig', $parameters);
}

UserInterestsType.php

class UserInterestsType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    $builder
        ->add('interest', EntityType::class, [
            'class' => Interest::class,
            'choice_label' => 'name',
            'expanded' => true,
            'multiple' => true
        ])
        ->add('update', SubmitType::class);
    }
 }

Проблема

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что при отправке формы это создает экземпляр объекта UserInterest, связанного с user, но с несколькими выбранными Interest в качестве массива, а не с несколькими UserInterest.

Как я могу сделать это надлежащим образом в Symfony, чтобы разрешить одну форму и простую логику контроллера, чтобы пользователь мог загрузить страницу, выбрать свои интересы из нескольких типов флажков, нажать «Сохранить», а затем, когда формаперезагружены они автоматически заполняются как предыдущий выбор?

1 Ответ

7 голосов
/ 05 июля 2019

Ваше первое решение слишком сложно для того, чего вы пытаетесь достичь. Если вы просто хотите, чтобы пользователь выбрал некоторые интересы, вам не нужен объект UserInterest.

Единственное использование, которое я могу придумать для новой сущности, предназначенной для этого отношения, - это если отношение имеет некоторые дополнительные свойства, которые вы хотите сохранить, например, дату начала отношения, может быть, порядок или приоритет, или что-то, что вам нужно. Если единственные данные, которые вы собираетесь хранить, это userId и InterestId, то новая сущность не принесет вам ничего, кроме сложности. Вам также не нужен CollectionType (вы все равно не создаете новый интерес к этой форме). Перейдите к простой связи ManyToMany между пользователем и интересом

 User:
  type: entity
  manyToMany:
    interests:
      targetEntity: Interest
      inversedBy: users
      joinTable: 
        ## name will be the name of the table storing your entities 's relations
        ## Beware not to give it a name already defined for an entity table (like your UserInterest wich you don't need anymore)
        name: users_interests 
        joinColumns:
          user_id:
            referencedColumnName: id
        inverseJoinColumns:
          interest_id:
            referencedColumnName: id

Interest:
  type: entity
  manyToMany:
    users:
      targetEntity: User
      mappedBy: interests

Затем вы можете использовать простой множественный EntityType в форме, где data_class - это User, а класс вашего типа сущности - это Interest:

class UserInterestsType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
    $builder
        ->add('interests', EntityType::class, [
            'class' => Interest::class,
            'choice_label' => 'name',
            'expanded' => true,
            'multiple' => true,
            'query_builder' => function (EntityRepository $er) {
    return $er->createQueryBuilder('u')
        ->orderBy('u.name', 'ASC');
}, 
        ])
        ->add('update', SubmitType::class);
    }
 }

Тогда предположим, что вы хотите получить пользователей, разделяющих определенный интерес или интересы конкретного пользователя, у вас будут запросы такого типа в существующих хранилищах пользователей и интересов:

// UserRepository: All users sharing one (or more) interests
$em = $this->getEntityManager();
$repository = $em->getRepository('YourNamespace:User');
$query = $repository->createQueryBuilder('u')
    ->innerJoin('u.interests', 'i')
    ->where('i.id = :interest_id')
    ->setParameter('interest_id', 5) // just for the example
    ->getQuery()->getResult();

// InterestRepository: All interests of one user 
$em = $this->getEntityManager();
$repository = $em->getRepository('YourNamespaceYourBundle:Interest');
$query = $repository->createQueryBuilder('i')
    ->innerJoin('i.users', 'u')
    ->where('u.id = :user_id')
    ->setParameter('user_id', 1)
    ->getQuery()->getResult();
...