Reputation: 6042
I'm in a bit of a design bind. I have a series of questions, and I want a user to enter a score for each question. There's a 1:* relationship between questions and scores, but on this particular form the user should only be able to enter one score per question. So, how can I create a form type that would automatically link the score to each question, like:
1. blah blah blah? Score: // user enters a score
2. blah blah blah? Score: // user enters a score
etc.
I can't divulge my entities due to a NDA, but suffice it to say, Question is on the 1 side, and Score is on the * side. Question::getScores()
and Question::setScores($scores)
are available to me, as are Score::getQuestion()
and Score::setQuestion($question)
.
If this was straight PHP, it wouldn't be a problem. Symfony2's form component is a bit convoluted, so I'm not sure how to proceed.
Upvotes: 0
Views: 135
Reputation: 2017
What you want to accomplish is to create a Score object for each question in the form on submit for the current user.
To accomplish this, first create a form type for the Score object.
<?php
// src/Acme/Bundle/Form/Type/ScoreType.php
// ...
$builder->add('ranking', 'integer')
This will allow your application to create Score objects via a form.
Now, in your Question form type, you'll want to embed a non-mapped Score form (for reasons discussed below), ie.
<?php
// src/Acme/Bundle/Form/Type/QuestionType.php
// ...
$builder->add('question')
$builder->add('score', new ScoreType(), array('mapped'=>false))
I assume that you currently have a setup similar to this, except you are probably using a collection type on 'scores' with the ScoreType. However, if this form is meant to be seen by the current user, then you are not going to want to display a collection. You would rather only display one, the one attached to the current user. Symfony cannot know this logic, since it is specific to your business logic.
This is where events come in. Please see http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
My approach would be to bind an EventSubscriber to the Question form. You should probably listen to PRE_SET_DATA event and a SUBMIT event.
Your PRE_SET_DATA listener should inspect the incoming Question object for information about what score it should put into the "score" form. For example, if the entity manager is injected into your subscriber, you might ask the EM if this user has a score already for this particular question, and if so grab it and place it as the data in "score". If not, create a new blank Score object and associate it to this question and the current user.
Now, once a form is submitted, listen to SUBMIT and do some logic there with the score object. This is why we don't map it to the question, because its a 1:*. Our form is a 1:1. These events are where you do your logic to make the connection. During POST_SUBMIT you could grab the Score object and call $score->setQuestion() with the form's data.
I realize this is a little vague and somewhat rushed answer but I hope it guides you in the right direction.
Upvotes: 1