Hello. Made a vote and it became necessary to prohibit a second vote. Decided through user id. To do this, created a table and in it two fields user_id and poll_id. That is, when entering a vote, we look at the table for all the current voting id, take the current user id, and if there are matches, this user already had this vote, then we prohibit him from voting here, if the user id does not match any voting id, then we give him to vote and write to the table id voting and user id. Tell me please, I think correctly? Or piled on garbage? And this table should be connected with user and poll tables?

  • The right approach. Just do not look for all those who voted on this survey and then compare with the user id. Immediately look for the presence of a table row with the user id and vote id. If there is no such line, then give a vote. - Visman
  • The direction is correct, you can slightly correct it in trifles. Take COUNT records for the current user and vote, you do not need the records themselves. If zero records - you can vote, if not zero - you can not. Above you almost the same wrote, I support. I just add that COUNT enough for you to use: transfer less data from SQL, spend less RAM. - AK
  • one
    COUNT is not much better, but LIMIT 1 better :) - Visman
  • You do not take into account that after one sample you do not find the user, and before you insert it, it takes time for it to appear there. - Vladimir Gamalyan
  • @VladimirGamalian how will it appear there if the recording happens only after the vote? - Alexey

2 answers 2

Your decision is correct and adequate. Add a unique composite key to the table (user_id, poll_id), then the database itself will not allow identical entries in the database and, consequently, several votes of one user by one vote. Foreign keys should also be added to the user and poll tables.

Before voting, make a request for this table using a unique composite key and, if there is a record, do not allow voting, you can also write this selected record to the cache so that you do not have to access the table once again.

It is possible, but not necessary, for additional information to add there the date and time when the user voted, the voting statistics will be visible here, and in the future you can add different functionality related to restricting voting by time or number of votes for a certain interval.

  • And you can also add how a person voted, so that a person who voted, for example, could cancel his vote / re-vote. - Visman

It seems to work, here is the controller code:

 public function actionPoll($id, $user_id, $poll_id) { $single = Poll::getOne($id); $getdata = PollUser::getData($user_id, $poll_id); $u = Yii::$app->user->id; if ($u != $getdata->user_id && $id != $getdata->poll_id) { if ($single->load(Yii::$app->request->post())) { if ($single->count1) { $single->updateCounters(['count1' => 1]); } if ($single->count2) { $single->updateCounters(['count2' => 1]); } if ($single->count3) { $single->updateCounters(['count3' => 1]); } Yii::$app->db->createCommand("INSERT INTO poll_user (user_id, poll_id) VALUES ($u, $id)")->execute(); return $this->redirect("/site/poll/?id=$single->id&user_id=$u&poll_id=$single->id"); } } else { return $this->render('pollonlyresult', ['single' => $single, 'getdata' => $getdata]); } return $this->render('poll', ['single' => $single, 'getdata' => $getdata]); } 

Take a vote. We take the data from the check table. We get the login user id - check for matches in the check table - if there are no matches, then we vote and record the current user and vote in the table. Redirect to the results page. If there is a match, then immediately redirect to the page with the results. It seems to be so, many thanks to all who answered.