PHP checking if username in multiple tables - php

I am trying to check if a passed in username is in either one of 3 tables. If it is then it exists and will return true, or else it will return false. Currently it just returns true no matter what.
$stmt = $conn->prepare("SELECT * FROM Table1 INNER JOIN Table2 INNER JOIN Table3 WHERE Table1.username = :name OR Table2.username = :name OR Table3.username = :name");
$stmt->bindParam(':name', $_POST["username"] );
$num_rows = $stmt->execute();
if ($num_rows > 0)
{
echo "true";
}
else
{
echo "false";
}

It's way better to use UNION in that case.
$sql = 'SELECT 1 FROM Table1 WHERE username = :name
UNION
SELECT 1 FROM Table2 WHERE username = :name
UNION
SELECT 1 FROM Table3 WHERE username = :name';
$stmt = $conn->prepare($sql);
$stmt->bindParam(':name', $_POST["username"] );
$qry = $stmt->execute();
if ($stmt->rowCount() == 0) {
// no match
} else {
// match
}

Related

Why the whole Table is locking during a MYSQL TRANSCTION? [duplicate]

transaction Query
mysqli_begin_transaction($conn);
$sql = "UPDATE foldertable SET trashed = 1 WHERE serverToken = (SELECT serverToken from servertoken where userToken = ? limit 1) and
(folderId = ?
or
RootFolderPath LIKE
CONCAT (
(SELECT RootFolderPath FROM foldertable WHERE serverToken = (SELECT serverToken from servertoken where userToken = ? ) AND folderid = ? limit 1)
,'/'
, ?
,'%'
)
)";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "sisii", $data["userToken"], $id, $data["userToken"], $id, $id);
if (!mysqli_stmt_execute($stmt)) {
echo mysqli_stmt_error($stmt);
$serverError = true;
return;
}
// echo "\n\n affected rows " . mysqli_affected_rows($conn);
if (mysqli_affected_rows($conn) > 0) {
sleep(15);
// Insert into bin folder
$sql = "INSERT INTO binfolder (serverToken , folderId) value ( (SELECT serverToken from servertoken where userToken = ? limit 1) , ?)";
$stmt = mysqli_stmt_init($conn);
mysqli_stmt_prepare($stmt, $sql);
mysqli_stmt_bind_param($stmt, "si", $data["userToken"], $id);
if (!mysqli_stmt_execute($stmt)) {
echo mysqli_stmt_error($stmt);
$serverError = true;
return;
}
if (mysqli_affected_rows($conn) > 0) {
$success = true;
mysqli_commit($conn);
}
}
Insert Query
INSERT INTO foldertable(serverToken) SELECT (123456)
Problem
if execute the insert query after transaction started but the insert does not have to wait for transaction complete . Because the update query on transaction does lock row involved with insert query.
What I wanted
the Insert query will run immediately if it does not contain the same serverToken needed in Insert query.
Thank You in Advance.

Mysql/PHP Json nested array

I got issue with nested array which seems are not Json object for some reason. When i try for e.g access jsonData["user"] it works, but when i try go deeper such as jsonData["user"]["photo_url"] then it's treated like a string and i cant access the value.
Current code:
<?php
require_once("db_connection.php");
$userId = $_GET["user_id"];
$query = "WITH user AS (SELECT id, JSON_OBJECT('display_name', u.display_name, 'photo_url', u.photo_url) AS user FROM users u WHERE id = :userId), info AS (SELECT id, JSON_ARRAYAGG(JSON_OBJECT('text', text, 'start_at', start_at, 'end_at', end_at, 'status', status)) AS information FROM report GROUP BY id), img AS (SELECT report_id, JSON_ARRAYAGG(JSON_OBJECT('name', name)) AS images FROM report_images GROUP BY report_id), cmt AS (SELECT report_id, COUNT(*) AS totalcomments FROM report_comments rc JOIN users u ON rc.user_id = u.id GROUP BY report_id) SELECT u.user, info.information, img.images, cmt.totalcomments FROM report r JOIN user u ON u.id = r.user_id LEFT JOIN info ON info.id = r.id LEFT JOIN img ON img.report_id = r.id LEFT JOIN cmt ON cmt.report_id = r.id";
$stmt = $db->prepare($query);
// Bind our variables.
$stmt->bindValue(":userId", $userId);
// Execute.
$stmt->execute();
$result = $stmt->fetchAll();
if (count($result) > 0) {
$toJson = json_encode($result);
echo $toJson;
} else {
$toJson = json_encode("Error");
echo $toJson;
}
?>
Old code which worked:
<?php
require_once("db_connection.php");
require_once("functions.php");
$userId = $_GET["user_id"];
$query = "SELECT * FROM report WHERE `user_id` = :userId";
$stmt = $db->prepare($query);
// Bind our variables.
$stmt->bindValue(":userId", $userId);
// Execute.
$stmt->execute();
$result = $stmt->fetchAll();
if (count($result) > 0) {
foreach ($result as $key => $value) {
$result[$key]["user"] = getUserById($db, $value["user_id"]);
}
$toJson = json_encode($result);
echo $toJson;
} else {
$toJson = json_encode("Error");
echo $toJson;
}
?>
Because you are aggregating some of the values as JSON in your query, you need to decode those first before attempting to use the values and then JSON encode the whole result set. You need to do that as you fetch the data, so replace:
$result = $stmt->fetchAll();
with:
$result = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$row['user'] = json_decode($row['user']);
$row['images'] = json_decode($row['images']);
$row['comments'] = json_decode($row['comments']);
$result[] = $row;
}

SQL Select count multiple columns and sort

So I'm trying to sort from highest prestiges and then highest experience (xp)
public function getRank($user, $skill, $mode) {
$skill2 = strtolower($skill)."_xp";
$skill3 = strtolower($skill)."_prestiges";
$stmt = $this->conn->prepare("SELECT (
SELECT COUNT(*) FROM hs_users WHERE mode = :mode AND (
$skill3 >= u.$skill3 AND $skill2 >= u.$skill2
)
) AS rank
FROM hs_users u
WHERE username = :user AND mode = :mode2
LIMIT 1");
$stmt->bindParam(":user", $user);
$stmt->bindParam(":mode", $mode);
$stmt->bindParam(":mode2", $mode);
$stmt->execute();
return $stmt->fetchColumn();
}
At the moment I'm getting duplicate rankings, two people are rank 1.
For example
if someone is prestige 1 and 3,000,000 experience and then someone is prestige 0 and 4,000,000 experience they achieve the same ranking, as to the second person is suppose to be rank 2.
I've been trying ORDER BY but it doesn't seem to be working. I'm not too experienced with SQL queries, if you have any pointers or could help me that'd be great.
If prestige is the primary ranking attribute:
$stmt = $this->conn->prepare("SELECT id, $skill3, $skill2
FROM hs_users
WHERE username = :user
AND mode = :mode
");
$stmt->bindParam(":user",$user);
$stmt->bindParam(":mode",$mode);
if($stmt->execute()){
$user = $stmt->fetch(PDO::FETCH_ASSOC);// get the users id, prestige and experience level
}
$higherPrestiges = array();
$stmt = $this->conn->prepare("SELECT id
FROM hs_users
WHERE $skill3 >= :skill3
AND mode = :mode");
$stmt->bindParam(":skill3",$user[$skill3]);
$stmt->bindParam(":mode",$mode);
if($stmt->execute()){
while($row = $stmt->fetch(PDO::FETCH_COLUMN)){ //get all users that have higher prestige
$higherPrestiges[$row] = $row;
}
}
if(count($higherPrestiges) > 0){
$higherPrestiges_implode = implode(",",$higherPrestiges);
}else{
$higherPrestiges_implode = "0";
}
$lowerExperiences = array();
$stmt = $this->conn->prepare("SELECT id
FROM hs_users
WHERE $skill3 = :skill3
AND $skill2 < :skill2
AND mode = :mode");
$stmt->bindParam(":skill2",$user[$skill2]);
$stmt->bindParam(":skill3",$user[$skill3]);
$stmt->bindParam(":mode",$mode);
if($stmt->execute()){
while($row = $stmt->fetch(PDO::FETCH_COLUMN)){//get users with lower experience with the same prestige
$lowerExperiences[$row] = $row;
}
}
if(count($lowerExperiences) > 0){
$lowerExperiences_implode = implode(",",$lowerExperiences);
}else{
$lowerExperiences_implode = "0";
}
$stmt = $this->conn->prepare("SELECT COUNT(id)
FROM hs_users
WHERE mode = :mode
AND id IN(".$higherPrestiges_implode.")
AND id NOT IN(".$lowerExperiences_implode.")");
$stmt->bindParam(":mode",$mode);
if($stmt->execute()){
$rank = $stmt->fetch(PDO::FETCH_COLUMN);//get number of users that have higher or equal prestige and exclude the ones with lower experience
}
Just replace references to "id" in the queries with the column name for primary keys in your table
I do realize the last 3 queries can be combined with subqueries in the IN clause, but this should make it easier to understand

Alternate query using if statement in PHP

I'm trying to run an alternate query if the initial query fails (it does because the id I'm searching for in this instance only exists in one of the databases being joined) using an if statement and I've constructed it like so:
<?php
require_once($_SERVER['DOCUMENT_ROOT'].'/php/link_costreport_2013.php');
$id = $_GET['id']; //ID # For page/query
if($query = $link->prepare("SELECT locale.id, locale.provider_num, locale.provider_name, locale.state, locale.city,
finstat_ca.coh_and_banks, finstat_ca.temp_investments, finstat_ca.notes_receivable, finstat_ca.accounts_receivable, finstat_ca.other_receivables,
finstat_ca.afun_and_ar, finstat_ca.inventory, finstat_ca.prepaid_expenses, (finstat_ca.other_cur_assets + finstat_ca.due_from_other_funds) as other_cur_assets, finstat_ca.total_current_assets,
finstat_fa.total_fixed_assets,
finstat_olta.investments, (finstat_olta.dep_on_leases + finstat_olta.due_from_owners_officers + finstat_olta.other_assets) as all_olta, finstat_olta.total_other_assets, finstat_olta.end_assets,
finstat_cl.accounts_payable, finstat_cl.salaries_wages_fees_payable, finstat_cl.payroll_taxes_payable, finstat_cl.notes_loans_payable, finstat_cl.deferred_income, finstat_cl.total_current_liabilities,
(finstat_cl.total_current_liabilities - (finstat_cl.accounts_payable + finstat_cl.salaries_wages_fees_payable + finstat_cl.payroll_taxes_payable + finstat_cl.notes_loans_payable + finstat_cl.deferred_income)) as all_other_cl,
finstat_ltl.mortgage_payable, finstat_ltl.notes_payable, finstat_ltl.unsecured_loans, finstat_ltl.other_long_term_liabilities, finstat_ltl.total_long_term_liabilities,
finstat_talfb.total_fund_balance, finstat_talfb.total_lia_plus_fb
FROM `locale`
INNER JOIN `finstat_ca`
ON locale.id = finstat_ca.id
INNER JOIN `finstat_fa`
ON locale.id = finstat_fa.id
INNER JOIN `finstat_olta`
ON locale.id = finstat_olta.id
INNER JOIN `finstat_cl`
ON locale.id = finstat_cl.id
INNER JOIN `finstat_ltl`
ON locale.id = finstat_ltl.id
INNER JOIN `finstat_talfb`
ON locale.id = finstat_talfb.id
WHERE locale.id = :id
LIMIT 1")){
} else {
$query = $link->prepare("SELECT id, provider_num, provider_name, state, city
FROM `locale`
WHERE id = :id
LIMIT 1");
}
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
echo json_encode($results);
Basically it defaults to the single table where the ID does exist and only pulls a couple fields as opposed to the large statement above it. My only issue is that my code here is not working. My JSON only says false when I echo it. It obviously should not.
Is there an error in my code here?
Thanks in advance
:edit: I should note that when I enter an ID that exists in all the tables joined, the correct result (json) is displayed on the page.
I believe the problem is that even if ID does not exist in the first query, the $query variable still has a proper query in it and there is nothing false about it. That's not what you should be if-testing.
I think you should be testing $results.
This shows you the logic.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/php/link_costreport_2013.php');
//ID # For page/query
$id = $_GET['id'];
$sql_1 = "SQL CODE FOR QUERY 1";
$sql_2 = "SQL CODE FOR QUERY 2";
$query = $link->prepare($sql_1);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
if (!$results)
{
$query = $link->prepare($sql_2);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
}
echo json_encode($results);
However as you can see there are a few lines of code that are repeated inside the if-statement that very similar to code that was just before the if-statement. Perhaps with a loop that loops twice but breaks out if $results is not false would be neater.
<?php
require_once($_SERVER['DOCUMENT_ROOT'] . '/php/link_costreport_2013.php');
//ID # For page/query
$id = $_GET['id'];
$sql[] = "SQL CODE FOR QUERY 1";
$sql[] = "SQL CODE FOR QUERY 2";
foreach ($sql as $sql_query)
{
$query = $link->prepare($sql_query);
$query->bindParam(':id', $id);
$query->execute();
$results = $query->fetch(PDO::FETCH_ASSOC);
if ($results)
{
break;
}
}
echo json_encode($results);
The world is your oyster.

how to shorten function query?

hello i have this function:
function mail_exists($email){
global $db;
$email = sanitize($email);
$query = $db->query("SELECT Email FROM table1 WHERE Email= '$email' ");
$check = $query->num_rows;
$query2 = $db->query("SELECT Email FROM table2 WHERE Email= '$email' ");
$check2 = $query->num_rows;
return ($check > 0 || $check2 > 0) ? true : false;
}
first of all i would like to know how i can shorten it by using only one query and second thing is, why this does not work when using two queries? both tables have a different structure. in table1 the field email is no. 16 and on table2 it is field no.6.
thanks alot.
First of all you made a logic error *here in the last lines: $query->num_rows; should be: $query2->num_rows; and then resulting into:
function mail_exists($email){
global $db;
$email = sanitize($email);
$query = $db->query("SELECT Email FROM table1 WHERE Email= '$email' ");
$check = $query->num_rows;
$query2 = $db->query("SELECT Email FROM table2 WHERE Email= '$email' ");
$check2 = $query2->num_rows; // *here
return ($check > 0 || $check2 > 0) ? true : false;
}
Second, you should be using two different queries if you are dealing with two completely different contexts. Don't join queries when you don't need to. If you are just counting rows you can easily do:
function mail_exists($email){
global $db;
$email = sanitize($email);
$query = $db->query("SELECT COUNT(*) FROM table1 WHERE Email= '$email' ");
$query2 = $db->query("SELECT COUNT(*) FROM table2 WHERE Email= '$email' ");
$count1 = $query->fetch_row();
$count2 = $query2->fetch_row();
return ($count1[0] || $count2[0]);
}
The SQL COUNT() function is there to give you the most performant way to count rows.
You might try:
SELECT t1.Email from table1 t1 inner join table2 t2 on t2.Email=t1.Email WHERE t1.Email = '$email'
and then:
return $query->num_rows > 0;
I'm not a PHP expert, so your mileage may vary.
Use can UNION ALL to return an overall count:
SELECT Email
FROM (
SELECT Email FROM table1 WHERE Email= '$email'
UNION ALL
SELECT Email FROM table2 WHERE Email= '$email') t
Or you can use SELECT COUNT(Email) to return the count.

Categories