Unable to get COUNT(*) result from structured SQL statement - php

I've been working on a SQL statement that checks the database to see if feedback has been left for a specific qr_id from a specific uuid within 24 hours. The original code works as intended, but obviously to be more secure I wanted to change the code to a structed SQL statement instead.
$uuid = "DB8962A3-BC7A-481F-9D7E-C1FC7F74E50E";
$qrid = "2147483647";
$query = sprintf("SELECT COUNT(*) FROM `feedback` WHERE uuid = '%s' AND qr_id = '%s' AND created_on > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 DAY))", mysql_real_escape_string($uuid), $qrid);
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
$size = $row['COUNT(*)'];
if ($size > 0){
echo 'Unable to leave feedback as user has left feedback for this employee within 24 hours.';
}else{
echo 'User has not left feedback for this employee within 24 hours, continue.';
}
The above works perfectly fine, if the count is above 0 then it stops the user posting. Here's my attempt at converting it to a structured SQL statement:
$stmt = $this->conn->prepare("SELECT COUNT(*) FROM `feedback` WHERE uuid = ? AND qr_id = ? AND created_on > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 DAY))");
$stmt->bind_param('si', $uuid, $qrID);
$result = $stmt->execute();
$size = $result['COUNT(*)'];
$stmt->close();
if ($size = 0){
// do post, return true
return true;
}else{
return false;
// do not post, return false
}
I have tried printing the result value and it's always 1, and trying to echo the $size variable returns nothing.

You need to fetch the result, try this:
$stmt->bind_param('si', $uuid, $qrID);
$stmt->execute();
//here you bind result to variable $size
$stmt->bind_result($size);
$stmt->fetch()
$stmt->close();
if ($size == 0){
// do post, return true
return true;
}else{
return false;
// do not post, return false
}

Related

do while loop php with multiple conditions

I am posting full code here for make my situation more clear.
<?php
require '../includes/env.php';
require '../includes/db.inc.php';
$total_campaigns = 0;
$total_checked_campaigns = 0;
$checked_campaigns_ids ="0";
$current_campaign_id = 0;
$c_rull = 1;
$c_daily_limit = 0;
/*get all live campaigns count*/
$total_campaigns = get_total_campaigns($conn);
/*check if any campaign available for send data*/
if($total_campaigns>0){
do {
//get one campaign id from all available campaigns.
$c_id = get_campaign($total_campaigns,$total_checked_campaigns,$checked_campaigns_ids,$current_campaign_id,$conn);
/*this while loop is checking that selected campaign have reached daily limit or not,if above campaign id reached limit, it should get another possible campaign id, if there no any campaign id avaialble
get_campaign function will return 0 and we will stop the loop*/
} while(!(($c_id == 0 || $total_checked_campaigns <= $total_campaigns) && is_daily_limit_allow($c_id,$c_daily_limit,$conn)));
echo $c_id;
}
function get_campaign($total_campaigns,$total_checked_campaigns,$checked_campaigns_ids,$current_campaign_id,$conn){
$c_status = 1;//live
$c_lead_status = 0;//not processed
$selectCampaignQuery = "SELECT * FROM tbl_software_campaigns WHERE c_lead_status = ? AND c_status = ? AND c_id > ? AND c_id NOT IN($checked_campaigns_ids) ORDER by c_id ASC LIMIT 1";
$stmt = $conn->prepare($selectCampaignQuery);
$stmt->bind_param("iii", $c_lead_status,$c_status, $current_campaign_id);
$stmt->execute();
$selectCampaignResult = $stmt->get_result();
if ($selectCampaignResult->num_rows==0) {
if($total_checked_campaigns==0){
$update_campaigns_query = "UPDATE tbl_software_campaigns SET c_lead_status = 0 WHERE c_status = 1";
$update_campaign_result = mysqli_query($conn,$update_campaigns_query);
$selectCampaignQuery = "SELECT * FROM tbl_software_campaigns WHERE c_lead_status = ? AND c_status = ? AND c_id > ? AND c_id NOT IN($checked_campaigns_ids) ORDER by c_id ASC LIMIT 1";
$stmt = $conn->prepare($selectCampaignQuery);
$stmt->bind_param("iii", $c_lead_status,$c_status, $current_campaign_id);
$stmt->execute();
$selectCampaignResult = $stmt->get_result();
}
}
if ($selectCampaignResult->num_rows>0) {
global $total_checked_campaigns;
global $c_daily_limit;
global $checked_campaigns_ids;
$row = mysqli_fetch_assoc($selectCampaignResult);
$c_id = $row['c_id'];
$c_daily_limit = $row['c_daily_limit'];
// we are updating total checked campaign count here as well updating comma seperated list of checked campaign id here in below two line
$total_checked_campaigns = $total_checked_campaigns+1;
$checked_campaigns_ids = $checked_campaigns_ids.",".$c_id;
//return campaign id for process the data
return $c_id;
}else{
//return 0 because there no any campaign available to process data
return 0;
}
}
function get_total_campaigns($conn){
$stmt = $conn->prepare("SELECT COUNT(c_id) AS total_campaigns FROM tbl_software_campaigns WHERE c_status = 1");
$stmt->execute();
$total_result = $stmt->get_result();
$row = mysqli_fetch_assoc($total_result);
$stmt->close();
return $row['total_campaigns'];
}
function is_duplicate($EMAIL,$conn){
$query = "SELECT lead_id FROM tbl_software_leads WHERE lead_email = ?";
$stmt = $conn->prepare($query);
$stmt->bind_param("s", $EMAIL);
$stmt->execute();
$duplicate_result = $stmt->get_result();
$stmt->close();
if ($duplicate_result->num_rows>0){
return true;
}else{
return false;
}
}
function is_daily_limit_allow($CAMPAIGN,$LIMIT,$conn){
if($LIMIT>0){
$limit_query = "SELECT count(*) as today_total FROM tbl_software_leads WHERE DATE(lead_time)=CURDATE() AND lead_camp_id =? AND lead_status = 1";
$stmt = $conn->prepare($limit_query);
$stmt->bind_param('i',$CAMPAIGN);
$stmt->execute();
$limitrow = $stmt->get_result()->fetch_assoc();
$todaysrecord = $limitrow['today_total'];
if($todaysrecord<$LIMIT){
return true;
}else{
return false;
}
}else{
return true;
}
}
?>
Now Let me explain my goal.
What I am looking to do is
on start its checking how many campaigns available there!
if campaign available more than 0, I am getting one campaign id and marking that campaign as checked campaign using get_campaign function
get_campaign function giving me campaign id and if there no any campaign available for process, its give me 0 as id.
if there 0 as id, I do not want do anything since it means there no any campaign available for handle the data
if get_campaign give me any campaign id, I need to check that its reached daily limit or not with is_daily_limit_allow function, if its reached that limit, I need to get new id using get_campaign function and check its daily limit.
I am trying to achieve above thing with while loop but its not working properly and running for infinity time.
Basically when
if campaign id is 0, I want stop the loop
if total checked campaigns equal to total campaigns, I want stop the loop because it means we have checked all campaigns and none are available for process the data
if current campaign id allow to process data and have not daily limit, I want stop the loop.
I should also clear that when
$c_daily_limit = 0;
means there no any daily limit in that campaign.
I hope its clear everything now and will help to expert here on stackoverflow.
Let me know if anyone can help me for solve the puzzle.
Thanks!
You said
if campaign id is 0, I want stop the loop
if total checked campaigns equal to total campaigns, I want stop the loop because it means we have checked all campaigns and none are
available for process the data
if current campaign id allow to process data and have not daily limit, I want stop the loop.
So, it makes straightforward conditions as below,
while($c_id != 0 && $total_checked_campaigns < $total_campaigns && is_daily_limit_allow($c_id,$c_daily_limit,$conn));
Try below snippet once
do {
echo $c_id;
echo "<br>";
$c_id = get_campaign($total_campaigns);
} while (($c_id == 0 || $total_checked_campaigns <= $total_campaigns) && is_daily_limit_allow($c_id));
here I changed condiotions as per your trying to get
(($c_id == 0 || $total_checked_campaigns <= $total_campaigns) && is_daily_limit_allow($c_id))
as i understand can you try this code
do {
echo $c_id;
echo "<br>";
$c_id = get_campaign($total_campaigns);
} while (($c_id != 0 && $total_checked_campaigns <= $total_campaigns) || !is_daily_limit_allow($c_id));
or
while(!(($c_id == 0 || $total_checked_campaigns <= $total_campaigns) && is_daily_limit_allow($c_id)))

PHP for loop only works every second row

in my current project I want to split 10 users from a queue into 2 teams with 5 users each.
When 10 users are in the queue the function create_new_lobby() is executed. In this function the match is created and all users should be assigned to the teams in an intermediate table. With a for loop all users should be assigned to the match. Currently the for loop only takes every second user (0, 2, 4, 6, 8). The values 1, 3, 5, 7 & 9 are apparently skipped by the for loop.
Where is the error here?
<?php
function create_new_lobby() {
global $connection;
$timestamp = date("Y-m-d H:i:s", strtotime(date('h:i:sa')));
$stmt = $connection->prepare("INSERT INTO competition_game (create_time) VALUES (?)");
$stmt->bind_param("s", $timestamp);
$stmt->execute();
$stmt->close();
$stmt = $connection->prepare("SELECT competition_match_id FROM competition_game ORDER BY competition_match_id DESC LIMIT 0, 1");
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
$competition_match_id = $row['competition_match_id'];
$stmt->close();
for($player = 0; $player <= 9; $player++) {
$status_queue = 1;
$stmt = $connection->prepare("SELECT * FROM competition_queue WHERE competition_queue_status = ? AND DATE_ADD(competition_queue_activity ,INTERVAL 20 MINUTE) >= NOW() ORDER BY competition_queue_id ASC LIMIT ?, 1");
$stmt->bind_param("ss", $status_queue, $player);
$stmt->execute();
$result = $stmt->get_result();
while($row = $result->fetch_assoc()) {
$user_id = $row['user_id'];
$stmt1 = $connection->prepare("INSERT INTO competition_game_player (competition_match_id, user_id) VALUES (?, ?)");
$stmt1->bind_param("ss", $competition_match_id, $user_id);
$stmt1->execute();
$stmt1->close();
}
$stmt->close();
$status_leave = 2;
$stmt = $connection->prepare("UPDATE competition_queue SET competition_queue_status = ? WHERE user_id = ? AND competition_queue_status = ?");
$stmt->bind_param("sss", $status_leave, $user_id, $status_queue);
$stmt->execute();
$stmt->close();
}
}
?>
Current result:
Expected result:
The for loop works as it should and you can check that by placing an var_dump($payer) inside the for loop;
The increment in the for loop is given by the third statement, the $player++, which means $player = $player + 1;
If you would want to have a different looping step, you can add a different expression for the third statement in the for loop.
e.g.
for($player = 0; $player <= 9; $player++) {
var_dump($player);
}
exit;
The code snippet will output 0 1 2 3 4 5 6 7 8 9
for($player = 0; $player <= 9; $player += 2) {
var_dump($player);
}
exit;
The code snippet will output 0 2 4 6 8
I hope this helped you better understand the for loop.
The actual problem you are facing is created by the logic that you have made with SQL and not by the for loop

Why is store_result() not returning num_rows equivalent to mysqli Regular Statement?

I've been combing through previous questions and trying many solutions but cannot figure this out. I'm trying to convert this query to a Prepared Statement:
$query = mysqli_query($this->con, "SELECT * FROM notifications WHERE user_to='$userLoggedIn' ORDER BY id DESC");
Here is what I have:
$query = $this->con->stmt_init();
$query->prepare('SELECT * FROM notifications WHERE user_to=? ORDER BY id DESC');
$query->bind_param('s', $userLoggedIn);
$query->execute();
$query->store_result();
$qty = $query->num_rows;
$query_result = $query->get_result();
Below this code I have variables being used like this:
if($qty == 0) {
echo "<li class='no-more-posts' style='height: 0px; text-transform: uppercase;'>- You have no notifications! -</li>";
return;
}
$num_iterations = 0; //Number of messages checked
$count = 1; //Number of messages posted
while($row = $query_result->fetch_assoc()) {
if($num_iterations++ < $start)
continue;
if($count > $limit)
break;
else
$count++;
$user_from = $row['user_from'];
etc.etc.
What I am getting is blank result in my dropdown. If I change the while statement back to the original while($row = mysqli_fetch_array($query)) { (which I know is wrong and from old statement) my result is always returning the li No More Posts to Show. This tells me that $qty = $query->num_rows; is returning 0. Based on documentation my understanding is that once I buffered the result set with store_result() I could call $qty = $query->num_rows; right after. What am I missing here?
I'm certain this isn't the most efficient way to do things, but it's all I have on it; decided to break the statement up.
First I did a statement for the count:
$query_count = $this->con->stmt_init();
$query_count->prepare('SELECT COUNT(*) FROM notifications WHERE user_to=?');
$query_count->bind_param('s', $userLoggedIn);
$query_count->execute();
$query_count_result = $query_count->get_result();
$rows_count = $query_count_result->fetch_array();
$qty = array_shift($rows_count);
Then I did a statement for the data:
$query = $this->con->stmt_init();
$query->prepare('SELECT * FROM notifications WHERE user_to=? ORDER BY id DESC');
$query->bind_param('s', $userLoggedIn);
$query->execute();
$query_result = $query->get_result();
It solved my problem & everything works as expected. I know there is a better way to do this, so if someone has that suggestion great. In the meantime this will have to do.

New SQL PDO query from result

I'm very new to PDO SQL queries. I have the following code which works well. When the result returns only 1 row, I then want to set that row to valid = FALSE". How do I do that?
$sql = "SELECT * FROM `passcodes` WHERE `passcode` = '$passcode' AND `valid` = TRUE";
$stmt = $DBcon->prepare($sql);
$stmt->execute();
$count = $stmt->rowCount();
if($count == 1) {
//do this
} else {
//do that
}
Yet another solution.
IF you interested in "else" section mentioned above, you can combine elegant solution from #YourCommonSense with checking how much rows was changed in UPDATE. MySQL returns such info!
$sql = "UPDATE `passcodes` SET `valid` = FALSE WHERE `passcode` = ? AND `valid` = TRUE";
$DBcon->prepare($sql)->execute([$passcode]);
if ($stmt->rowCount() == 0) {
// do this when nothing found
}
I then want to set that row to valid = FALSE". How do I do that?
this is what SQL is for.
$sql = "UPDATE `passcodes` SET `valid` = FALSE WHERE `passcode` = ? AND `valid` = TRUE";
$DBcon->prepare($sql)->execute([$passcode]);
this is all the code you need.
This will work with count of result rows equal or greater than 1.
I recommend to use placeholders for prepared statements:
$sql = "SELECT `id` FROM `passcodes` WHERE `passcode` = ? AND `valid` = TRUE";
$stmt = $DBcon->prepare($sql);
$stmt->execute([ $passcode ]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
if($rows) {
//do this
$sql = "UPDATE `passcodes` SET `valid` = FALSE WHERE `id` = ?";
$stmt = $DBcon->prepare($sql);
foreach ($rows as $r) {
$stmt->execute([ $r['id'] ]);
}
} else {
//do that
}

My select statement with PDO its not working correctly

Here I store my login session in my $userId variable to get my id:
$ userId = $_SESSION['result']['id'];
Here I store a $_SESSION['where'] if the user wants to search for some name:
if(isset($_POST['sendFiltro'])){
$search = $_POST['search'];
if(!empty($search) && $search != 'Name:'){
$_SESSION['where'] = "AND name LIKE '%$search%'";
header('Location: index2.php?exe=adminis/admins');
}else{
unset($_SESSION['where']);
header('Location: index2.php?exe=adminis/adminis');
}
}
Here I do my select statment to get my admins to show in a table:
$pag = (empty($_GET['pag']) ? '1' : $_GET['pag']);
$max = 10;
$first = ($pag * $max) - $first;
$where = isset($_SESSION['where']) ? $_SESSION['where'] : '';
$readAdmin = $pdo->prepare("SELECT * from admins WHERE id != :id {$where} ORDER BY name ASC, level ASC LIMIT :first, :max");
$readAdmin->bindParam(':id', $userId, PDO::PARAM_INT);
$readAdmin->bindParam(':first', $first, PDO::PARAM_INT);
$readAdmin->bindParam(':max', $max, PDO::PARAM_INT);
$readAdmin->execute();
$readAdminRows = $readAdmin->rowCount();
if(!$readAdminRows)
{
echo 'There are no recors in admins table';
}
else
{
//I show my table
}
I have 20 recors in my Admins table, and its always saying that I dont have recors in my admin table.
Do you see some error in my code for this to be happening?
If i remove this from my sql statment WHERE id != :id it works, but I dont want to show in the table the current admin with his session.
$readAdminRows = $readAdmin->rowCount();
The rowCount() function always returns 0 if you configure PDO to use unbuffered queries:
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
I'd suggest instead that you try to fetch the first row of the result set, and if the first fetch still returns nothing, then you have no matches.

Categories