I'm trying to build voting system for my web page (Laravel 5). Now, any user can vote multiple times, I want to fix it.
Here is my code in php:
public function addVote()
{
$bikepoint = $this->bikepoint->find($id);
$userid = \Sentry::getUser()->id;
$votesid = \DB::table('bikepoints')->select('votesuid')->where('votesuid', 'LIKE' , $userid)->get();
if (...) {
$bikepoint->votes = $bikepoint->votes + 1;
$bikepoint->votesuid = $bikepoint->votesuid . $userid . '; ';
echo 'Success!';
}
else {
echo 'Fail!';
}
$bikepoint->save();
}
My DB table:
id title votes votesuid
1 point1 2 93; 22;
2 point2 3 92; 28; 47;
3 point3 45 ...
4 point4 32 ...
5 point5 12 ...
So when user click the "Add vote" button, a function adds its ID to the votesuid field and one vote to the votes field.
I want to check if the user has already voted by checking if his ID is placed in the votesuid field. And, if so, the user cannot vote anymore.
For example, users with IDs 92, 28 and 47 should not be able to vote another time.
As suggested by others in the comments, yes, you do need to change your system so that each vote has it's own record on a table.
So create a Votes table and a Laravel model class for it, and give your Users model class a hasMany() relationship to Votes.
That's actually not too much work, is it?
But now then the solution to your question becomes trivially easy -- ie:
$votes = Sentry::getUser()->votes;
As things stand, you would need to do sub-string LIKE queries, which are much harder to write, and will also give you major performance problems when your DB starts getting bigger, so yes, you definitely need to be refactoring it now.
Related
My goal is that when I encode a student for a payment. He (student) can follow 2 trainings per payment. (this is the ceiling - 1 payment = 2 trainings)
In my form Payment, I encode a student for example Menier.
The student is entitled to two trainings, (this is the ceiling)
In my form Training: I encode 2 trainings for the student Menier.
My first question: how can I block the number of trainings by two?
(so, if I encode another training, it must block!)
My second queston, if I encode 2 payments for the same student. The student is entitled to 4 trainings. How to create this type of algorithm?
Here is my code for now, I know it's not a lot...
Edit 05-10-2019 - Controller Training
public function store(Request $request)
{
$request->validate([
'date_seance' => 'required',
'hour_start' => 'required',
'hour_end' => 'required',
'fk_motorbike' => 'required',
'fk_former' => 'required',
'fk_student' => 'required',
'fk_typeseance' => 'required'
]);
$date_seance = $request->get('date_seance');
$hour_start = $request->get('hour_start');
$hour_end = $request->get('hour_end');
$fk_motorbike = $request->get('fk_motorbike');
$fk_student = $request->get('fk_student');
$fk_former = $request->get('fk_former');
$fk_typeseance = $request->get('fk_typeseance');
$payments = Payment::where('fk_student', $request->get('fk_student'))->first();
if(!isset($payments)){
return redirect()->route('trainings.index')
->with('error', 'No payment, no training! ');
}
$thisStudentsTrainings = Training::where('fk_student', $fk_student)->get();
if(count($thisStudentsTrainings) >= 2){
return redirect()->route('trainings.index')
->with('error', 'The ceiling is 2 trainings! ');
}
$thisStudentsPayments = Payment::where('fk_student', $request->get('fk_student'))->get();
if( (count($thisStudentsPayments) * 2) < count($thisStudentsTrainings) ) {
return redirect()->route('trainings.index')
->with('error', 'test!');
}
else{
Training::create($request->all());
return redirect()->route('trainings.index')
->with('success', 'Add');
}
}
Do you have an idea of how I could solve my problems, I am still a beginner in laravel.
For Watercayman
Thank you for your time.
This is not too bad to do. Since the payment is not directly associated with a specific training (ie you have a credit system), you can do this pretty easily with a couple of queries.
My first question: how can I block the number of trainings by two?
Start with the basics and find the number of trainings in the database for this student:
$thisStudentsTrainings = Training::where('fk_student', $fk_student)->get();
Or you can come in from the reverse for this simply query:
$student = Student::with('trainings')->get();
$thisStudentsTrainings = $student->trainings;
Then, to limit to two trainings (without payment consideration yet):
if(count($thisStudentsTrainings) >= 2){ too many trainings }
Now that you have a count of trainings, if you also want to make sure they have a payment in the system, lets get the payments:
$thisStudentsPayments = Payment::where('fk_student', $request->get('fk_student'))->get();
To check if they have paid for trainings, you now have both pieces of data that you need. You just have to figure out if they have paid for the right amount of trainings based on 2 payments = 1 training. So:
if( (count($thisStudentsPayments) * 2) < count($thisStudentsTrainings) ) {
// They have not made enough payments!
}
My second queston, if I encode 2 payments for the same student. The student is entitled to 4 trainings. How to create this type of algorithm?
The above will work for 2 or 4 or whatever you want.
Now, if you want to enforce a max of 2 trainings per each payment, we can check on this too. BUT, this is starting to get a little complex or circular in the logic. If you can avoid this, it will be a lot easier. But, let's check on the max of 2 per payment, which is just the adding an equals check, AFTER the one above:
if( (count($thisStudentsTrainings) >= count($thisStudentsPayments) * 2) {
// They are at their limit of trainings based on their payments!
// Note we include >= so that if they have purchased 2 trainings,
// this blocks them from a 3rd until they pay again.
}
This should solve your issue. However, you didn't ask, but I assume you don't want a student to allow a training if they have already used up a payment. IE if they've taken a training and they have 'spent their credit', they should not be allowed to take the training. If this is important to you, I suggest that in another part of your program, you write to the database when a payment has been consumed. So - if a student uses 2 trainings and has paid for them, maybe a boolean field on the Payment model spent (or something to indicate the payment is no longer valid). You could also remove the payment from the system if you don't need historical data. But, assuming you do, and you use $payment->spent, you can still do the above algorithm, just add the spent line to the query something like:
$student = Student::with(['trainings' => function($query){
$query->where('spent', 0)
}])->get();
Then all the rest should be the same. This isn't cut & paste, but I think now that you have separated out payments and trainings, this should be a pretty easy solve to understand based on the above. :)
I want to show an online status on my website if an other user is online. So for example if user A wants to know if user B is available, I want to show an online sign.
I know that there is a function in WordPress called is_user_logged_in() but this function works only for the current user. https://developer.wordpress.org/reference/functions/is_user_logged_in/
So is there anyone who has an idea how I can get this done?
This is the logic:
if ( user_online( $user_id ) ) {
return 'Online';
} else {
return 'Absent';
}
You might use Transients API to get users's status.
Create a user-online-update function that you hook on init. For example:
// get logged-in users
$logged_in_users = get_transient('online_status');
// get current user ID
$user = wp_get_current_user();
// check if the current user needs to update his online status;
// status no need to update if user exist in the list
// and if his "last activity" was less than let's say ...15 minutes ago
$no_need_to_update = isset($logged_in_users[$user->ID])
&& $logged_in_users[$user->ID] > (time() - (15 * 60));
// update the list if needed
if (!$no_need_to_update) {
$logged_in_users[$user->ID] = time();
set_transient('online_status', $logged_in_users, $expire_in = (30*60)); // 30 mins
}
This should run on each page load, but the transient will be updated only if required. If you have a large number of users online you might want to increase the "last activity" time frame to reduce db writes, but 15 minutes is more than enough for most sites.
Now to check if the user is online, simply look inside that transient to see if a certain user is online, just like you did above:
// get logged in users
$logged_in_users = get_transient('online_status');
// for eg. on author page
$user_to_check = get_query_var('author');
$online = isset($logged_in_users[$user_to_check])
&& ($logged_in_users[$user_to_check] > (time() - (15 * 60)));
The transient expires in 30 minutes if there's no activity at all. But in case you have users online all the time it won't expire, so you might want to clean-up that transient periodically by hooking another function on a twice-daily event or something like that. This function would remove old $logged_in_users entries...
Source: https://wordpress.stackexchange.com/a/34434
First get the user id of the user B by
$user_id_B = get_current_user_id();
Now here give the condition for the particular user B to check whether he is online or not
if(is_user_logged_in()){
if( $user_id_B == 'user id of B')
{
return 'Online'; (or echo 'online';)
}
}
By this you will get the presence of user B.
Please note, similar questions have been asked multiple times.
**** Though, not this one as far as my search goes! ****
The goal:
I need help on how to build a script that shows the page with user settings. It should be based on account level and if the user_id matches with the variable of 'id' in the url. So, basically.. the admin should always be able to see the user settings no matter if the user_id matches the 'id' from the url.
The problem:
I can't get it to work with the two variables (user status = 'id' in url, and if the user is admin? Then always show) in a good way, since I don't want to duplicate the "juicy" stuff in two places.
My current state:
I'm thinking something like this:
#DB:USERS
user_id user_name user_level ....
1 ADAM 3 (admin)
2 BRYAN 1 (suspended)
3 CODY 2 (user)
4 DAVID 3 (admin)
CODE:
<?php
// Get the logged in user data..
$sql = "SELECT * FROM users where user_name = '".$_SESSION['username']."'";
$user_level = $row["user_level"];
$query... (SELECT * #DB:USERS);..
$url_id = $_GET['id'];
$user_id = $row['user_id'];
if ($url_id == $user_id) {
#Show all the juicy user setting stuff#
} else {
echo 'ACCESS DENIED';
}
?>
So far so good, but how to add the step that says, if the user status is equal to 3 (admin).. then show the jucy stuff anyway?
Thanks in advance!
If I understood your question, you need to test if user is admin in addition of the test of user ID, use or condition :
// not sure of variable name for userlevel
if ($url_id == $user_id || $_SESSION['userlevel'] == 3) {
#Show all the juicy user setting stuff#
} else {
echo 'ACCESS DENIED';
}
This is one of my first applications out of tutorials so I don't know how to express my issue well.
Well I have these 2 tables:
User ( id, code )
Hours ( id, user_id, created)
I want to know how I can add an entry to the Hours table using the user_code.
I tried to grab the data of the User table with the code value and then findBy and pass for the patchEntity but it did not work.
I don't have a whole lot of information to work with, but I'll give it a go.
I want to know how I can add an entry to the Hours table using the
user_code
You mention using patchEntity, so that's updating information that's already there. Assuming user_code is the 'code' column you're talking about there, first find the user by his code:
$users_tbl = TableRegistry::get('Users');
// find the user
$user = $users_tbl->findByCode($user_code)->first();
if ($user) {
// replace '$this->request->data() with whatever patch data you wanted
$users_tbl->patchEntity($user, $this->request->data(), [
'associated' => ['Hours']
]
if ($users_tbl->save($user)) {
// success!
} else {
// error!
}
} else {
// error!
}
It will also depend on how you have the data you passed in (where my '$this->request->data() is, or whatever your array might be) - it needs to match the right column names and be in the correct format listed here.
However, this is updating the data. Just adding the data, you can load the hours table and add a new entry with the user_id acquired from the user search:
$hours_tbl = TableRegistry::get('Hours');
$hours = $hours_tbl->newEntity([
'user_id' => $user->id // $user populated from same method earlier
]);
/* assumed 'id' was autoincrementing and 'created' was populated
through Timestamp behavior */
if ($hours_tbl->save($hours)) {
// yay!
} else {
// boo
}
What is the best aproace of enriching c5 user's attributes.
I have non C5 table with users information this information was created on old cms (non c5), and im now building new site with c5 would like to know best aproach of migrating users.
Is it good idea to use SQL query or should i use php script for enriching, I already created users in to c5 and manualy added email addresses for "anchor point" for later enrichment.
Would be realy glad if someone could tell or maby could lead to some examples.
finaly managed by myself, its rather simple:
i exported external users to php array and used c5 user functions to add users and after enrich them my example:
$external_users = array({
array('id'=>'1', 'name'='JON', 'email'=>'blank#blank.blank', 'last_name'=>'DOE', 'attr1'=>'smthing', 'attr2'=>'123'),
array(...), ...
});
foreach($external_users as $singleUser_data){
$email = $singleUser_data['email'];
$ui = UserInfo::getByEmail($email);
if (!is_null($ui)) {
// Email is already in use, so let's not create the user
return;
}
$userData['uName'] = $singleUser_data['name']." ".$singleUser_data['lastname'];
//users later need to reset password
$userData['uPassword'] = 'asd52465465456454asd';
$userData['uPasswordConfirm'] = 'asd52465465456454asd';
//user registererd
$ui = UserInfo::register($userData);
set_new_user_group($ui);
enrichAtributes($ui, $singleUser_data);
}
function set_new_user_group($ui){
// assign the new user to a group
$g = Group::getByName('GroupName');
$u = $ui->getUserObject();
$u->enterGroup($g);
}
function enrichAtributes($ui, $singleUser_data){
$ui->setAttribute('atr_handler1', $singleUser_data['attr1']);
$ui->setAttribute('atr_handler2', $singleUser_data['attr2']);
}
Resource:
User registration programaticly and seting group
User information documentation (setting attributes)