I have three tables: groups, questions and answers.
groups is connected to questions in a one to many relationship. Similarly, questions has a one to many relationship with answers. Editors provide an answer to a given question after an admin submits the groups and questions.
How do I create this in Laravel 5? I think to creating a pivot table for group_question and question_answer is the right place to start, but I am not sure because I don't know how to later select questions and answers together. Should I instead use json and save all questions and answers to one record?
There are a number of ways to tackle your problem in Laravel, but the easiest way is probably by using the hasManyThrough relationship. Which can be defined in your Group class something like this:
class Group extends Model {
public function answers(){
return $this->hasManyThrough('App\Answer','App\Question');
}
}
just be sure your tables have the following foreign key fields
groups
id - integer
name - string
questions
id - integer
group_id - integer
text - string
answers
id - integer
question_id - integer
text - string
you can read up on more on this in the laravel docs under eloquent relationships.
See more from Laravel 5's docs on the hasManyThrough relationship here.
Related
I have a table participants where each participant belongs to a conference, which is an entry in the table conferences. Further, each participant can provide one answer which are stored in the table answers.
Now, I need a query which gets all the answers from all participants which belong to the current conference.
In particular, I would like to paginate the results, thus I am hoping for a more sophisticated approach than to simply fetch all answers and then check if they belong to a participant in this conference.
To be clear, my tables store basically the following information:
participants - id, conference_id
conferences - id
answers - id, participant_id
You could use HasManyThrough.
I think the example in the Laravel Doc fits perfect to your case.
Laravel Doc example
You can use hasMany and hasOne relation ship of Laravel Eloquent Model, and add more constraint when you use Eloquent Relation Ship query (As Laravel document say All Eloquent Relation Ship is query builder, so you can add constraints using where) to get results you expect.
This question already has answers here:
Doctrine2: Best way to handle many-to-many with extra columns in reference table
(13 answers)
Closed 7 years ago.
I have "customers", "products" and "versions" tables.Each customer, can have more than one product, and each product has more than one version. I have created many-to-many relation "customers_products" and everything works perfect.
Also I have created one-to-many relation between "products" and "versions".
QUESTION:
How to add an extra column (version_id) in "customers_products" table so I can build form where user can choose products and version to create new customer.
Once an association has data, it's no more an association.
You have to implement two ManyToOne instead of a ManyToMany.
See this great answer on this question for a full example.
You can get a lot of other examples by googling the title of your question.
Adding an extra column to the association of a many-to-many it actually changes the meaning of that relationship. In order to represent that with Doctrine, you'd need to change the association to be a one-to-many/many-to-one between the three entities.
You'll end up with three entities in your domain model, which would allow you to access to the version of a CustomerProduct entity.
You can read a bit more detailed explanation in Doctrine's docs.
This is probably more of a conceptual question but I am trying to find the best way to make a view that displays one quiz question at a time and checks the answer.
Currently my MySQL table has the following columns: id, category_id, quiz_question, answer_one, answer_two, answer_three, correct_answer.
My controller uses the following to get the quiz questions:
$quizzes = Quiz::where('category_id',$category_id)->simplePaginate(1);
In my view, I go through the process of doing the asnwer ordering manually
{{$quiz->quiz_question }}
<a onclick="this.innerHTML='Wrong'">{{ $quiz->answer_one }}</a>
<a onclick="this.innerHTML='Right'">{{ $quiz->correct_answer }}</a>
<a onclick="this.innerHTML='Wrong'">{{ $quiz->answer_two }}</a>...etc.
and was probably just going to use JavaScript/JQuery to check for the right answer.
Conceptually this feels like a pretty bad way to do this and I am still not sure how to randomize the order of the answers if they are from the same DB table like this. Overall is there a better way to go about this (Display 1 quiz question, and display answers in random order, check without a DB query)? Thanks in advance.
Do not keep the answers on the client side in any form.
Instead, just get the questions and paginate it on the client side. If you absolutely need to validate answers one by one, then fire up AJAX requests.
Or you can just let the person attempt the whole quiz and post the questions with users' answers and validate them on the server side. Then you return the result/score/answers.
Regarding your query about checking without DB query, you shouldn't do it. If you absolutely need it then save answers in an object, rather than in the DOM. Again, it can't be any more "not recommended".
Edit:
You should first divide it into these tables. You can't randomize the order of display of the options without a hack from the first table.
And don't name the columns like answer_one, answer_two, answer_three, correct_answer. In this manner the only way to recognize the answer in by the column name correct_answer. Column name shouldn't give a hint about the correct answer. It should be stored somewhere else.
questions
id
question - the question body
categories
id
category - name of the category
question_categories (one question may belong to multiple categories)
id
question_id
category_id
options
id
question_id
option - option text
answers
id
question_id
option_id
Now what you do is you randomize the order of options
$questions = Question::where('category_id', $category_id)->
with(['options' => function ($query) {
$query->orderBy(DB::raw('RAND()'));
}])
->get();
To randomly order the options we used ORDER BY RAND().
Now you just send the option_id and can check if it is the correct answer on the server side.
Edit - 27th March
You can use the following models.
Question
QuestionCategory
Category
Option
Answer
You can use the following relationships.
Question belongsTo QuestionCategory
QuestionCategory belongsTo Category
Question hasMany Option
Question hasOne Answer
But creating a QuestionCategory model doesn't really scale well. So if you don't want to do that you can use Polymorphic relationships. You can use category table to store basically all types of categories, not just question categories. In that case, you need to modify the categories tables to add the type of taxonomy. If you don't understand any of this polymorphic relationship thing, please find it in the official Laravel documentation https://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations
I have 3 tables in my database. A link table, a question table and an answer table. In link I store evaluationmoments. In question I store the questions that can be asked in the evaluations. In answer I store the answers that a user has given in the evaluation.
What I want to do is get all the answers that were given for a specific evaluation.
Link has the primary key link_ID.
Question has the primary key question_ID.
Answer has the primary key anwer_ID.
Link and Question are connected with a many-to-many relationship. Therefore there is a pivot table called link_question. With the keys link_id and question_id.
In my laravel models I have these functions:
class Link extends Ardent{
public function question(){
return $this->belongsToMany('Question');
}
class Question extends Ardent{
public function link(){
return $this->belongsToMany('Link');
}
This all works fine. However, now I want to give the answer table a many-to-one relation with this pivot table. For every entry in the pivot table there are multiple answers. How would I got about implementing this in laravel? I don't have a model for the pivot table so I can't just add a function there.
I have a Question model which has a one to many relationship with an Answer model.
Now I want to add upvote/downvote funcionality to both of these models, do I need to create two tables like VotesQuestions and VotesAnswers or can I somehow manage with one? If so, how?
You can use a polymorphic relationship. This is built into Laravel. Documentation is here. The code shown here is for Laravel 4, but the functionality is the same for Laravel 5.
Create a votes table, and make sure it has at least two specific fields: votable_id and votable_type. In a database migration, you would use the statement $table->morphs('votable');, and it will create the two fields. You can have as many other fields as you like, but to make sure the relationship works, those two fields are required.
Next, setup the Vote model with the votable relationship. The name of this relationship should match the base name of the fields you created:
class Vote extends Eloquent {
public function votable() {
return $this->morphTo();
}
}
With this setup, you can now associate votes to any model you want. Go ahead and add the votes relationship to the Question and Answer models:
class Question extends Eloquent {
public function votes() {
return $this->morphMany('Vote', 'votable');
}
}
class Answer extends Eloquent {
public function votes() {
return $this->morphMany('Vote', 'votable');
}
}
You can now access the votes for any question/answer through the relationship:
$q = Question::first();
$qVotes = $q->votes; // Collection of votes for the question.
$a = Answer::first();
$aVotes = $a->votes; // Collection of votes for the answer.
You can also get the related question/answer model through the vote, if you ever need to:
$v = Vote::first();
$vRelated = $v->votable; // Will automatically be a Question or Answer object, depending on what the vote was for.
I would do an table for the question and when you want to up/downvote the question there should be a count column for both, otherwise you want to log it that an user can only vote for it once, so you need another table for user_id, question_id and type (up/down).
ofc you can handle it with one table, but that is really worth because you save many things that are not necessary.
you can create a table with an internal id, 1,2,3,4 and 1 is always the question or 0 and 2-xx (1-xxx) are always the answers. so you can handle it with one table
You could create a generic Votes model/table which has a field called "model" and "model_id" and then use reflection to get the correct object.