PHP, PDO, SQLite INNER JOIN Statement And Variable - php

I need to do a PHP PDO call to my db with an INNER JOIN and WHERE clause.
In navicat GUI this statement is running fine and i can see the results. The problem come out lather in php environment about string concatenation.
I would like to format this request so that it can be digested by php:
SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = $username AND T.username = $username;
what I tried to do
$sth = $db->prepare("SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = $username AND T.username = $username");
the return is an error indicating that there is no table with the variable name. Basically it takes the variable as the name of the table the return is an error indicating that there is no table with the variable name. Basically it takes the variable as the table name and not the table name as it should like (SELECT * FROM $username) jumping out the first part of statement).
The intent is to have all the records of table A where the username field is = to the username field of table B with value passed from a variable.
Thank for any suggestion to achieve my goal.
UPDATE
php is magic need to try and retray. At the end tish one help me to goal:
$username = ($_POST['username']);
$password = ($_POST['password']);
$statement = $db->prepare('SELECT p.* FROM `tsourcetb` as p LEFT JOIN `users`as s ON p.username = s.username WHERE s.username = :username;');
$statement->bindParam(':username', $username, PDO::PARAM_STR);
$statement->execute();
/* look here -> $statement->fetchall(PDO::FETCH_ASSOC) */
$array_select = $statement->fetchall(PDO::FETCH_ASSOC);
echo json_encode($array_select, JSON_PRETTY_PRINT);

<?php
$sth = $db->prepare("SELECT * FROM `tsourcetb` as T INNER JOIN users as U ON U.username = T.username WHERE U.username = ? AND T.username = ? ");
$sth->execute([$username,$username]);
$results = $sth->fetchall();
?>
wrapper your table name with backticks and also use placeholders

Try this:
$stmt = $db->prepare("SELECT * FROM tsourcetb as T INNER JOIN users as U ON U.username = T.username WHERE U.username = :username AND T.username = :username");
$stmt->bindValue(':username', $username, PDO::PARAM_STR);
$stmt->execute();
You need to bind a value with prepared statement:
Source: Docs

You have to bind parameters when you are making an dynamic query with PDO.
Change this in your query.
$username -> :username
And before you make the call
$yourQueryObj->bindValue(':username', $username, PDO::PARAM_STR);
That's why prepared statments are safer than regular variables as you assign it's type before it's sent for query.
You can read about it here
http://php.net/manual/en/pdostatement.bindvalue.php
You should be able also execute with array of parameters after preparing like that :
$sth = execute(array(':username'=> $username));

Related

How to pass multiple where clause variables to bind_param?

I am trying to do a multi query using prepared statements.
I am getting number of bind param errors :
Warning: mysqli_stmt::bind_param(): Number of variables doesn't match number of parameters in prepared statement in C:\wamp\www\c\index.php on line 35
Line 35 is:
$stmt->bind_param('i', $user_id);
Here is total codes:
I tried several examples but couldnt make it work.
Example 1:
$stmt->bind_param('i', $id); //output id from session
Example 2:
$stmt->bind_param('ii',$id, $user_id);
And some more tries too.
$id = $_SESSION['id']; // value comes from session and its full
$stmt = $mysqli->prepare("SELECT users.*, stores.*, products.* FROM stores, products, users WHERE users.id = ? AND stores.user_id = ? AND products.user_id = ?");
$stmt->bind_param('i', $user_id);
$stmt->execute();
$stmt->bind_result($id, $user_id, $pname);
$stmt->fetch();
$stmt->close();
echo $pname;
When I do queries in phpmyadmin codes works fine on $sql as following 2 queries:
$sql = "SELECT users.*, stores.*, products.*\n"
. "FROM stores, products, users\n"
. "WHERE ((users.id) AND (stores.user_id) AND (products.user_id))";
AND without php code
SELECT users.*, stores.*, products.*
FROM stores, products, users
WHERE ((users.id)
AND (stores.user_id)
AND (products.user_id))
This is the closest example :
I am having error:
Warning: mysqli_stmt::bind_result(): Number of bind variables doesn't match number of fields in prepared statement in C:\wamp\www\c\index.php on line 37
Line 37 is :
$stmt->bind_result($user_id, $username, $pname);
$id = $_SESSION['id'];
Closest code :
$stmt = $mysqli->prepare("SELECT users.*, stores.*, products.* FROM stores, products, users WHERE users.id = stores.user_id AND stores.user_id = products.user_id AND products.user_id = ?");
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($user_id, $username, $pname);
$stmt->fetch();
$stmt->close();
echo $pname;
Your prepared statement contains 3 questionmarks/placeholder. So you have to bind exactly 3 values.
I think this should work:
$stmt = $mysqli->prepare("SELECT users.*, stores.*, products.* FROM stores, products, users WHERE users.id = ? AND stores.user_id = ? AND products.user_id = ?");
$stmt->bind_param('iii', $user_id, $user_id, $user_id);
See examples at: http://php.net/manual/de/mysqli-stmt.bind-param.php
Here is working sample of the code, I had to change:
SELECT users.*, stores.*, products.* FROM
To
SELECT users.id, users.username, stores.user_id, stores.name, products.user_id, products.pname FROM
And rest of the code like so: and its working now, I wouldlike to know if its safe to use on a live and dynamic website ?
Can someone correct the code please.
Here is total working code
$id = $_SESSION['UserId'];
$stmt = $mysqli->prepare("SELECT users.id, users.username, stores.user_id, stores.name, products.user_id, products.pname
FROM stores, products, users
WHERE users.id = ?
AND stores.user_id = users.id
AND products.user_id = users.id");
$stmt->bind_param('i', $id);
$stmt->execute();
$stmt->bind_result($id, $username, $user_id, $name, $user_id, $pname);
$stmt->fetch();
$stmt->close();
echo $pname;
echo"<br>" .$name;
echo "<br>".$username;
I tried INNER JOIN AND LEFT JOIN (Mentioned in comment) but couldnt made both. work
EDİT :
Same query with INNER JOIN its working.
$sid = $_SESSION['UserId'];
$stmt = $mysqli->prepare("SELECT u.id, u.username, s.user_id, s.name, p.user_id, p.pname FROM stores AS s INNER JOIN products AS p ON p.store_id = s.store_id INNER JOIN users AS u ON u.id = p.user_id WHERE s.user_id = ?");
$stmt->bind_param('i', $sid);
$stmt->execute();
$stmt->bind_result($id, $username, $user_id, $name, $user_id, $pname);
$stmt->fetch();
$stmt->close();
echo $pname;
echo"<br>" .$name;
echo "<br>".$username;

MySQL prepare statement using variable

I am using below PHP + MySQL prepare statement to select values from database, passing the variable into the statement using function, however I could not get my wanted result. The problem is I don't know how to using the variable in the prepare statement.
Question:
Could you take a look whether the syntax I am using is correct?
public function getToken($committeeValue){
$stmt = $this->conn->prepare("SELECT u.token FROM users u INNER JOIN committee c ON u.email = c.email WHERE c.'$committeeValue' = 1");
$stmt->execute();
}
Please try the below one.
public function getToken($committeeValue){
$stmt = $this->conn->prepare("SELECT u.token FROM users u INNER JOIN committee c ON u.email = c.email WHERE c.".$committeeValue." = 1");
$stmt->execute();
}
I think you are made a mistake to appending a php variable within the string.Please try this.
You made the mistake of concatenating string in PHP.
So please try this below:
public function getToken($committeeValue){
$committeeValue = trim($committeeValue);
if(!empty($committeeValue)){
$query = "SELECT u.token FROM users u INNER JOIN committee c ON u.email = c.email WHERE c.".$committeeValue." = 1";
$stmt = $this->conn->prepare($query);
$stmt->execute();
}
}
Using var content directly is not safe because it allow to inject SQL statements.
The safe way is, in your case:
public function getToken($committeeValue){
$committeeValue = trim($committeeValue);
if(!empty($committeeValue)){
$query = "SELECT u.token FROM users u INNER JOIN committee c ON u.email = c.email WHERE c.? = 1";
$stmt = $this->conn->prepare($query);
$stmt->bindParam(1, $committeeValue);
$stmt->execute();
}
}
The query will be compiled without the var content so you dont have to worry about SQL injection.

Calling a second query if results are empty

I'm calling an INNER JOIN Query to display results from a user if they have information in both tables 1 & 2 - this works fine. However, If said user doesn't have information in both tables then my variables come back undefined.
So I'd like to call my INNER JOIN query and if the rows are empty for Table1, it will call a second query to display the results from Table2.
(Table2 definitely has information stored. Table1 is optional depending on the user)
I also want to display results from Tables 1 & 2 if another user has information in both, I can't seem to get it working. Here's what I have so far;
$sql="SELECT * FROM Table1 INNER JOIN Table2 ON Table1.username = Table2.username WHERE Table1.username='" . $_SESSION['username']['1'] . "'";
$result=MySQL_Query($sql);
if (mysql_num_rows($result)==0)
{
$sql2"SELECT * FROM Table2 WHERE username='" . $_SESSION['username']['1'] . "'";
$result2=MySQL_Query($sql2);
}
while ($rows=mysql_fetch_array($result)($result2))
{
$Username = $rows['username'] ." ";
$Email = $rows['email'] . " ";
}
echo $Email; ?>
You can rewrite your query with an outer join as follows:
select
t1.desired_info
t2.desired_info
from
table2 as t2
left outer join
table1 as t1
on (t2.username = t1.username)
where
t2.username = target_username;
The where clause will narrow the result set down to the user of interest and return 0 rows if the target_username does not exist. t2.desired_info will always come back while t1.desired_info will be null if that user is not present in that table.
You can inspect p1.desired_info in your php code first and if that does not appear then use p2.desired.
Echo the suggestion to use OUTER JOIN, which joins all the selected rows in the left table to matching rows in the right, or to an empty row if there are no matching rows on the right.
Also, I've rewritten to use PDO and a prepared statement, to show you how its done. The values in the variables $dbhost, $dbname, $dbuser and dbpassword are supplied by your code.
<?php
$dsn = "mysql:host=$dbhost;dbname=$dbname";
$dbh = new PDO($dsn, $dbuser, $dbpassword);
$sql = "SELECT *
FROM table2 t1
LEFT JOIN table1 t1 ON t1.username = t2.username
WHERE t2.username = :username";
// prepare() parses and compiles the query. Syntax error come out here.
$stmt = $dbh->prepare($sql);
// bindValue() handles quoting, escaping, type-matching and all that crap for you.
$stmt->bindValue(':username', $_SESSION['username']['1']);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_BOTH))
{
$Username = $rows['username'] ." ";
$Email = $rows['email'] . " ";
// and then do something useful with them
}
The use of a prepared statement here gives a significant measure of protection against SQL injection attacks. As usual, I leave error handling as an exercise for the reader.

Prepared statement, loop results to get more results

I have a query where I'm taking several results from a single table. I then need to loop through each result to get information from other tables, however, I can't get it to work.
Here's my code:
<?php
$type = 1;
if ($stmt = $cxn->prepare('SELECT username FROM users WHERE type = ?')) {
$stmt->bind_param('i', $type);
$stmt->execute();
$stmt->bind_result($username);
while ($stmt->fetch()) {
if ($stmt = $cxn->prepare('SELECT count FROM posts WHERE username = ?')) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->bind_result($result2);
$stmt->close();
}
}
$stmt->close();
}
?>
I get an error:
Call to a member function fetch() on a non-object
How do I fix this?
I would highly recommend a native SQL JOIN for this because it will avoid unnecessary overhead in sending potentially thousands of queries:
SELECT
u.username,
p.count
FROM
users u
LEFT JOIN // processed as LEFT OUTER JOIN so the syntax is interchangeable just fyi
posts p
ON u.username = p.username
WHERE
p.type = ?
Explaining LEFT JOIN only, we'll keep it simple =)
In the SQL above we start with username from the users table as a whole
users u just grants us the shortcut syntax for u.username so that SQL is readable and doesn't fubar
Next we want to attach the posts p table where u.username = p.username because we need the p.count for each username
Lastly we filter this conglomerate of data based on p.type being equal to something
Please note that are many things at play here depending on the DBMS. Such things include query optimizers, the exact point of filtering, etc... but that is far outside the scope of simply getting the hang of what we are trying to achieve conceptually so I will not go into detail because it will only cause confusion.
You are overwritting your stmt variable. You should use another one, like
$type = 1;
if ($stmt = $cxn->prepare('SELECT username FROM users WHERE type = ?')) {
$stmt->bind_param('i', $type);
$stmt->execute();
$stmt->bind_result($username);
while ($stmt->fetch()) {
if ($stmtCnt = $cxn->prepare('SELECT count FROM posts WHERE username = ?')) {
$stmtCnt->bind_param('s', $username);
$stmtCnt->execute();
$stmtCnt->bind_result($result2);
$stmtCnt->close();
}
}
$stmt->close();
}

Using two queries at the same time. PDO

Okay so, I don't really know anything about PDO, my friend just asked me to post this here since he's not very good at English. Anyway, this is how he explained it to me:
The code provided is supposed to get a couple of values, save them, and it's supposed to get something out of another table with the help of the values gotten from earlier. The problem according to my friend is that it doesn't get the second value.
Code:
$user_email = $_SESSION['user_email'];
$query = $db->prepare("SELECT username,id,password FROM user WHERE email=:email");
$query->bindParam(':email', $user_email, PDO::PARAM_INT);
$query->execute();
$row = $query->fetch();
$user_username=$row['username'];
$user_group=$row['group'];
$query_group = $db->prepare("SELECT color,name FROM group WHERE id=:id");
$query_group->bindParam(':id', $user_group, PDO::PARAM_INT);
$query_group->execute();
$row = $query_group->fetch();
$group_color=$row['color'];
$group_name=$row['name'];
The word group used as a table name needs to be enclosed in backticks. group is a reserved key word (GROUP BY clause).
SELECT
color,
name
FROM `group`
WHERE id = :id
Using the above would work.
You can shorten the entire code by using a JOIN clause too. As commented above by Prix, the code shall be:
$user_email = $_SESSION['user_email'];
$query = $db->prepare("SELECT
u.username,
u.id,
u.password,
g.color,
g.name
FROM user u
JOIN `group` g
ON g.id = u.id
WHERE u.email = :email");
// I think emails are supposed to be `PDO::PARAM_STR`
$query->bindParam(':email', $user_email, PDO::PARAM_INT);
$query->execute();
$row = $query->fetch();
$user_username = $row['username'];
$group_color = $row['color'];
$group_name = $row['name'];
You don't have group in your select statement .
If you don't use * in your select you must have the field name in your query .
$query = $db->prepare("SELECT username,id,password FROM user WHERE email=:email");
This query gives you only username,id,password back NOT the field group .
so try to use $row['group'] is wrong .
$user_group=$row['group'];
So also put group in your select statement
Place also group in backticks it's a reserved word
$query = $db->prepare("SELECT id, username, password, `group` FROM user WHERE email=:email");
This is also a reason for important variables (e.g for next query) to consider their validity.
if (isset($row['group'])) {
database logic
} else {
error
}
With this simple test you would have found the error itself.

Categories