Limit number of searches per user per week in php - php

I have developed a search page, which is only accessible to logged in users. But I want to limit search for each user to only 20 times in one week. One user will not be able to search for more than 20 times. Please help me how can I achieve this.

Implement two colums in the users table:
column 1 : search_counts -default 0
coumn 2 : search_timestamp -default 0
when a user initiate a search:
inspect the timmstap, if it is older than one week set it to current time (now) and set the counter to one and allow the search , if not, check the counter if its equal maximum allowed searches then abort it otherwise increment the counter and allow the search.
Here is an untested function to do this assuming you pass the couner and timstamp values from the user table to it:
function search_check($counter,$ts,$max=20,$period =7) {
$p = $period * 24 * 60 * 60;
$now = time();
if(($now - $ts) >= $p ){
//set the time stamp to now in DB
//set the counter to 1 in DB
return true;
}else {
if($counter < $max){ //
//increment the counter by 1 in DB
return true;
}else{
return false;
}
}
}
usage:
//retrieve counter and timestamp values from the DB users table
$can_search = search_check($counter,$ts);
if($can_search){
//search and return search result
}else{
echo "Sorry, maximum weekly searches reached"
}

Related

Calculating time difference between two db values for multiple rows

I have a database which holds two timestamps (date_ticket_reported, date_ticket_resolved), I want to caluclate the average time difference between these times for each resolved_by user_id.
Each row has a (resolved_by) column which corresponds to a user_id.
There will be multiple rows, for each user_id.
I have tried various approaches including the following.
ticket_model.php code
public function get_resolved_time_by_user($user_id){
$query1 = $this->db->select('resolved_date')->from('tickets')->where('resolved_by',$user_id)->get();
$resolved1 = $query1->row();
$query2 = $this->db->select('ticket_date_reported')->from('tickets')->where('resolved_by',$user_id)->get();
$reported1 = $query2->row();
$resolved2 = $resolved1->resolved_date;
$reported2 = $reported1->ticket_date_reported;
foreach($resolved2 as $row){
//Convert them to timestamps
$reported_dateTimestamp = strtotime($resolved2);
$resolved_dateTimestamp = strtotime($reported2);
$diff = $resolved_dateTimestamp - $reported_dateTimestamp;
return $diff;
}
}
Ticket view code
<p> Average Resolve Times <?php echo $this->ticket_model->get_resolved_time_by_user($user_id); ?> </p>
So to summarise; I want to display the average time between date_ticket_reported, date_ticket_resolved. For each user_id specified.
Any help would be awesome!
I have tried Malkhazi Dartsmelidze answer,
$this->db->query("SELECT
AVG(TIMESTAMPDIFF(SECOND, resolved_date, ticket_date_reported)) as timediff,
resolved_by as user
FROM tickets
GROUP BY resolved_by");
I get an error saying Object of class CI_DB_mysqli_result could not be converted to string
Where you say resolved_by as user. Should "user" be the user_id? ie should it say "resolved_by as user_id"?
You Can run only One Query With Myqsl:
SELECT
AVG(TIMESTAMPDIFF(SECOND, resolved_date, ticket_date_reported)) as timediff,
resolved_by as user
FROM tickets
GROUP BY resolved_by
This returns Average Time Difference in Seconds for Each User
Try this
$resolved2 = $resolved1->resolved_date;
$reported2 = $reported1->ticket_date_reported;
$diff = $resolved2 - $reported;
And then echo $diff and check what you are getting in $diff,

Need to iterate through DateTime appointments with multiple bookings

I have a MySql Database with peoples' names as varchars and appointment times as DateTime objects. I need to make a function that returns the next available time slot (DateTime format) found in the database, I'll use it to schedule people for that time slot.
Appointments are only on Tuesdays and Wednesdays. Whether it's Tuesday or Wednesday, 4 people can be seen at 9:00am, and 2 people can be seen at 10:30am.
This function returns the number of people that are booked for a given time slot (DateTime).
function getTimeSlotCount($dateTime)
{
// finds out how many people are scheduled for the given datetime
global $db;
$query = "SELECT * FROM appointments
WHERE AppointmentTime = :dateTime
ORDER BY AppointmentTime";
$statement = $db->prepare($query);
$statement->bindValue(':dateTime', $dateTime);
$statement->execute();
$count = $statement->rowCount();
$statement->closeCursor();
#var_dump($count);
return $count;
}
I plan to use a do while loop to iterate through timeslots. But I don't know how to iterate through appointment times that I mentioned using DateTime. Also how to compare the time portion of a datetime to a specific time of day?
function getNextAvailableTimeSlot()
{
$maxFor9am = 4;
$maxFor1030am = 2;
$isAvailableSlotFound = false;
do {
// How Do I: Assign next Timeslot to $AppointmentTime;
$numBooked = getTimeSlotCount($AppointmentTime)
if ($numBooked >= $maxFor9am && $HowdoIGetTimeFromAppointmentTime == 9am)
continue;
else if ($numBooked >= 2 && $HowdoIGetTimeFromAppointmentTime == 1030am)
continue;
else
$isAvailableSlotFound == true;
} while ($isAvailableSlotFound == false);
return $AppointmentTime;
}
EDIT: When an appointment is added to the database table. The person's name and a DateTime is entered for the record of the appointment.

Codeigniter Group By Returning Only First Row

I have a reservation module in codeigniter wherein I limit users to reserve the clubhouse for only 2 hours a day. I am currently creating a validation in codeigniter to limit their reservation. What I did was to select all the reservations, and group them by the rows having the same date in order to properly limit them. The problem is that the model I created is only returning 1 row, and not all the results. This means that my counter is just being changed by only one row, which I expect that all rows should affect the counter.
Below is my database table:
Basically, the second row isn't supposed to be inserted in the database because user '20130123' already has used up his maximum reservation for the day which is two hours. I provided the validation check below on checking whether the user has used up two hours of reservation, and my logic here is that I just subtract the reservation end with the reservation start. Using the table above just as an example and for my explanation, my problem is that in my model, the counter's value becomes only "2" because it only reads the first row (8 - 6 = 2), instead of "3" (result of the first row which is 2, then add the result of second row which is 1 : [(8-6) + (9-8)])
To sum it up, my problem lies on the counter's value, because it is only being added by the first row the query reads.
Here's my code.
Model:
function check_twohours_clubhouse()
{
$query = $this->db->select('*')->from('clubhouse_reservation')->where('username', $this->session->userdata('username'))->group_by('reservation_date')->having('count(reservation_date) > 1')->get();
$result = $query->result();
if($query->num_rows() > 0)
{
$ctr = '0';
foreach($result as $row)
{
$totalhour = $row->reservation_end - $row->reservation_start; // subtract reservation start to reservation end to get the number of hours
$ctr = $ctr + $totalhour;
}
$ctr = $ctr + ($this->input->post('reserveend') - $this->input->post('reservestart')); // add the selected "add reservation" hours to the counter
if($ctr > 2) // counter > 2 hours limit
{
return FALSE;
}
else
{
return TRUE;
}
}
else
{
return TRUE;
}
}
Controller:
function create_reservation_clubhouse()
{
$this->form_validation->set_error_delimiters('<div class="error">','</div>');
$this->form_validation->set_rules('datepick', 'Date', 'required|no_olddate');
$this->form_validation->set_rules('reservestart', 'Reservation Start', 'required|hourselection|unique_reserve_clubhouse|max_twohours');
if ($this->form_validation->run() == FALSE)
{
$this->template->load('user_template', 'view_userreservation_addclubhouse');
}
else
{
if($this->model_reservation_user->check_twohours_courtone())
{
if($query = $this->model_reservation_user->create_reservation_clubhouse())
{
$this->session->set_flashdata('reservefeedback', 'You have successfully reserved a date for the Clubhouse. Please wait for the administrators to accept your reservation.');
redirect('user_reservation/clubhouse');
}
}
else
{
$this->session->set_flashdata('reservefail', 'You cannot reserve more than two hours of Clubhouse per day.');
redirect('user_reservation/clubhouse');
}
}
}
You can calculate all this in sql using time_to_sec() and timediff() functions:
select reservation_date, sum(time_to_sec(timediff(reserveend, reservestart)) / 3600 as reserved_hours
from clubhouse_reservation
where username =...
group by reservation_date
having count(*)>1 --although it is not clear to me why you have this restriction
The above query would sum up for a given user per reservation date, the hours for which the clubhouse is reserved (3600 = number of secs in an hour).
In your php code you only need to check if the reserved_hours in the resultset is >2 or not.
I'm not really an expert with CI, therefore I can't really tell how to convert the above sql to CI. But I'm afraid that you have to use raw sql because of the way it sums the time.

PHP - Show more from user with more percentage

on our Site we have an Animation, that spins the Avatars from Users. The problem is, that this was really random. If user1 has more (1.00$) and user2 (0.50$), it can show more user2 avatars in the animation, than the user1.
The Avatars gets pushed in the array here (in value you get the amount)
SELECT avatar, SUM(value) FROM `game".$gamenum."` GROUP BY `value` DESC
while($row = mysql_fetch_array($rs)) {
$crd .= 'avatar.push(\''.$row["avatar"].'\');';
$i++;
}
and now here it gets random on the 44 Positions in the animation
for(var i=1; i <= 44; i++) {
var rand = getRandomInt(0,(avatar.length-1));
$(\'#img\'+i).attr("src",avatar[rand]);
}
and this is the "getRandomInt" function
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
I tried a much, but i dont find anything how to show the Avartars like the Percentage of the full amount
The Full amount in this example is: 1.50$. Like the amount from user1 + user2.
Can anyone help me?
First, you need to order the user's by their value in your MySQL query, instead of "grouping" them by value. Instead, if avatar is not the unique key, you should group by it.
You also need the sum of all values of all users. Calculate that in the while loop below.
SELECT avatar, SUM(value) FROM `game".$gamenum."` ORDER BY `value` DESC
$sum = 0;
while($row = mysql_fetch_array($rs)) {
$crd .= 'avatar.push(\''.$row["avatar"].'\');';
$i++;
$sum += $row["value"];
}
After this, you probably pass the avatar array and the total $sum value to JavaScript (front-end).
On the front-end side, instead of looping through the 44 images, loop through the avatars.
You also need to keep track of whether all the 44 images have been filled. In that case, we will need to end the loop.
// Keep track of number of images inserted
var imagesInserted = 0;
for(var i = 0; i < avatars.length; i++)
{
// Get avatar's value. Assuming that your JavaScript array contains the avatar's value at the second index and name at the first inde
var val = avatar[i][1];
// Get avatar's percent share in the 44 images
var n = getImagesShare(avatar[i][1], sumOfAllAvatars);
// Check whether 44 images are over
if(imagesInserted <= 44)
{
// Code to insert 'n' images for this user
// Increment the number of images inserted
imagesInserted += n;
}
else
{
// All 44 images have been inserted, end the loop
i = avatars.length + 1;
}
}
Finally, the function to calculate the number of images a user should get:
function getImagesShare(avatarValue, totalValue)
{
var numberOfImages = Math.floor((avatarValue/totalValue) * 44);
return numberOfImages;
}
The above is a basic implementation based on your code. Performance wise, you should do most of the processing related to displaying the number of images for each user on back-end side, and only display the data on the front-end side, in addition to some more functionality if needed.

Php pagination from Mysql Select * Where; If click on next page number, then displays all rows from Mysql

In input field user enters condition - what data to get from mysql. For example, user wants to get mysql rows where month is October (or 10).
Here I get user input $date_month = $_POST['date_month'];
Then mysql statement and code for pagination
try {
$sql = $db->prepare("SELECT * FROM 2_1_journal WHERE RecordMonth = ? ");
$sql->execute(array($date_month));
foreach ($sql as $i => $row) {
}
$number_of_fetched_rows = $i;
$number_of_results_per_page = 100;
$total_pages = ceil($number_of_fetched_rows / $number_of_results_per_page);
if (isset($_GET['page']) && is_numeric($_GET['page'])) {
$show_page = $_GET['page'];
if ($show_page > 0 && $show_page <= $total_pages) {
$start = ($show_page -1) * $number_of_results_per_page;
$end = $start + $number_of_results_per_page;
}
else {
$start = 0;
$end = $number_of_results_per_page;
}
}
else {
$start = 0;
$end = $number_of_results_per_page;
}
for ($page_i = 1; $page_i <= $total_pages; $page_i++) {
echo "<a href='__filter_mysql_data.php?page=$page_i'>| $page_i |</a> ";
}
}
So, user enters month (10), script displays all rows where month is 10; displays page No 1. But if user click on other page number, script displays all data from mysql (all months, not only 10)
What I see - when click on other page number, page reloads, that means that values of php variables "dissapears". As understand after page reload $date_month value is not set (has lost/"dissapears") ? How to keep the value? Or may be some better solution for pagination?
Update.
Behavior is following:
1) in input field set month 10 (October);
2) click on button and get displayed data from mysql where month is 10 (October); so far is ok
3) click on page number 2 and get displayed all data from mysql (all months, not only 10 (October))
Tried to use LIMIT however it does not help.
Possibly problem is related with this code
for ($page_i = 1; $page_i <= $total_pages; $page_i++) {
echo "<a href='__filter_mysql_data.php?page=$page_i'>| $page_i |</a> ";
}
When click on $page_i for not understandable (for me) reasons get displayed all (not filtered) data from mysql. If I use LIMIT also get displayed not filtered results from mysql....
Use LIMIT in your query, have a look at the following example , you can try something like :
SELECT
*
FROM
2_1_journal
WHERE
RecordMonth = ?
LIMIT [start_row],[number_of_rows_per_page]
So for example lets say you have 2 pages with 10 rows per page then the LIMIT for the 2 queries (one per page) will be:
1) LIMIT 0,10
2) LIMIT 10,10
You should change your query like this:
SELECT * FROM 2_1_journal WHERE RecordMonth = ? LIMIT = $number_of_results_per_page OFFSET ($page_number*$number_of_results_per_page);
Here you need to calculate the page number also and you should use the limit and offset concept of mysql.

Categories