PHP PDO Prepared Statement Query not substituting - php

I have a short segment of PHP code:
$stm = $db->prepare($sql);
$result = $stm->execute($params);
$params is the following
array(1) {
[0]=>
string(3) "why"
}
However, the $sql being sent to MySQL still contains a question mark according to the MySQL logs:
1 Query SELECT a.* FROM article a
LEFT JOIN article_links al on a.id = al.from_article_id
WHERE al.to_article = '?'
Is there something else I'm missing for substitution?

You don't need to have the single quotes around the question mark:
SELECT a.* FROM article a
LEFT JOIN article_links al on a.id = al.from_article_id
WHERE al.to_article = ?;

I suspect this is true:
$sql = "SELECT a.* FROM article a LEFT JOIN article_links al on a.id = al.from_article_id WHERE al.to_article = '?'"
The question mark should not be surrounded by quotes--this means it's a string instead of a parameter placeholder. Use just al.to_article = ?.

Related

Why does my PHP MYSQL Query not work with SUM?

I don't get it.
This PHP - MYSQL query does work:
$sql = mysqli_prepare($conn, 'SELECT O.*
FROM OFFER O
LEFT JOIN EVENT E ON E.OFFER_ID = O.KEY_ID
LEFT JOIN BOOKING B ON B.EVENT_ID = E.KEY_ID
WHERE O.KEY_ID = ? ');
$sql->bind_param('i', $keyId);
With SUM statement it doesn't work:
$sql = mysqli_prepare($conn, 'SELECT O.*,
SUM(CASE WHEN B.KEY_ID IS NULL THEN 0 ELSE 1 END) AS BOOKING_COUNT
FROM OFFER O
LEFT JOIN EVENT E ON E.OFFER_ID = O.KEY_ID
LEFT JOIN BOOKING B ON B.EVENT_ID = E.KEY_ID
WHERE O.KEY_ID = ? ');
$sql->bind_param('i', $keyId);
Error message:
Uncaught Error: Call to a member function bind_param() on boolean in ..snippet-ops.php(361) : eval()'d code:107
The query works in phpmyadmin though.Does anyone know why?
EDIT: SOLVED: The accepted Answer contains the solution in the comments (turning on report and a GROUP BY solved the issue.
EDIT2: When downgrading a question it would be good to know why otherwise the downgrade is useless.
Try surrounding your query string with double quotes instead of single quotes. Beware, that prepare might return false instead of a statement object. You should check this and react accordingly. Also make sure to close your statement after you're done with it.
Here (not tested):
<?php
$sql = "
SELECT O.*, SUM(CASE WHEN B.KEY_ID IS NULL THEN 0 ELSE 1 END) AS BOOKING_COUNT
FROM OFFER O
LEFT JOIN EVENT E ON E.OFFER_ID = O.KEY_ID
LEFT JOIN BOOKING B ON B.EVENT_ID = E.KEY_ID
WHERE O.KEY_ID = ?
GROUP BY O.KEY_ID";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param("i", $keyId);
$stmt->execute();
// do stuff with $stmt
$stmt->close();
} else {
echo $stmt->error;
}
?>
UPDATE: As can be seen in the comments, it was necessary to group by the column O.KEY_ID, or the prepare would return false.

Multiple mysql table joins with php?

Honestly I have no idea how to do what I am trying to do. I am not overly experienced in php nor in Mysql but I am trying and could use some help, preferably with working example code.
Problem: I have 3 tables
members
customfields
customvals
members contains:
membername | Id
customfields contains:
rank | name
customvals contains
fieldid | userid | fieldvalue
Table columns match at
customvals.userid=members.id
customvals.fieldid=members.rank
What I need to do is match the data so that when page.php?user=membername is called it displays on the page
Table1.membername:<br>
Table2.name[0] - Table3.fieldvalue[0]<br>
Table2.name[1] - Table3.fieldvalue[1]<br>
etc...
(obviously displaying only the information for the said membername)
The more working the code, the more helpful it is for me. Please don't just post the inner join statements. Also it is most helpful to me if you could explain how and why your solution works
So far here is what I have for code:
$profileinfocall = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`membername` = $username;";
$membercall = "SELECT * FROM members WHERE membername=$username";
$profileinfo = mysql_query($profileinfocall, $membercall);
while($row = mysql_fetch_array($profileinfo)) {
echo $row['membername'];
}
Obviously this doesn't work as I get the following errors:
Warning: mysql_query() expects parameter 2 to be resource, string given on line 534.
Warning: mysql_fetch_array() expects parameter 1 to be resource, null given in on line 535
While this is a very broad question and you have not provided any PHP code, you might want to break it down into various sections:
Establishing a connection to the database (with mysqli) and sending a query:
$c = mysqli_connect("localhost","user","password","db");
if (mysqli_connect_errno())
echo "Failed to connect to MySQL: " . mysqli_connect_error();
else {
$result = mysqli_query($c,"SELECT * FROM members");
while($row = mysqli_fetch_assoc($result)) {
echo "{$row['membername']}";
}
}
mysqli_close($c);
Tieing your tables together:
It is better to start off with a clear structure (including line breaks) when getting into the MySQL syntax. One way would be to have some sort of query skeleton:
SELECT tablealias.column, table2alias.field3
FROM table AS tablealias
LEFT|RIGHT|INNER JOIN table2 AS table2alias ON table.id=table2.id
WHERE (this and that = true or false, LIKE and so on...)
Breaking it down to your specific problem this would be:
SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`Id` = 'UserID to be searched for'
Improvements & Security measures:
But there is even more to it than meets the eye. If you have just begun, you might as well dive directly into prepared mysqli- statements. Given the query to get your members, the only changing part is the ID. This can be used for a prepared statement which is much more secure than our first query (though not as fast). Consider the following code:
$sql = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE (Table1.`Id` = ?)";
$c = mysqli_connect("localhost","user","password","db");
$stmt = $c->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_params("i", $userid);
$stmt->execute();
while ($stmt->fetch()) {
//do stuff with the data
}
$stmt->close();
}
$mysqli->close();
This SQL query should do it:
SELECT a.membername, a.Id, b.fieldid, b.userid, b.fieldvalue, c.rank, c.name
FROM members AS a
LEFT JOIN customvals AS b ON a.id = b.userid
LEFT JOIN customfields AS c ON b.rank = c.fieldid
WHERE a.Id = #MEMBERIDHERE#;

php pdo where clause

I have the following code for selecting from multiple tables where the order number matches.
$orderNumber = $_GET['orderNumber'];
$sql = $db->prepare("
SELECT
*
from `KC_Orders`
INNER JOIN
`KC_Payments`
on KC_Orders.orderNumber = KC_Payments.orderNumber
INNER JOIN
`KC_OrderStatus`
on KC_Orders.orderNumber = KC_OrderStatus.orderNumber
INNER JOIN
`KC_Statuses`
on KC_OrderStatus.statusID = KC_Statuses.statusID
WHERE
orderNumber= :orderNumber");
$sql->execute(array(':orderNumber' => $orderNumber));
$orderInfo = $sql->fetchAll();
Now when I var_dump($orderInfo); it returns: array(0) { } What is wrong? All the tables include the same $orderNumber field within it. If I take the WHERE part out it works just fine except it returns every row not just one. (obviosly).
Please help us!
You need to specify what the OrderNumber is from, and the * is from (what table). So try this new code:
$sql = $db->prepare("SELECT KC_Orders.* from `KC_Orders` INNER JOIN `KC_Payments` on KC_Payments.orderNumber = KC_Orders.orderNumber INNER JOIN `KC_OrderStatus` on KC_OrderStatus.orderNumber = KC_Order.orderNumber INNER JOIN `KC_Statuses` on KC_Statuses.statusID = KC_OrderStatus.statusID WHERE KC_Orders.orderNumber= :orderNumber");
Ordernumber in where clause should have table prefix if it exists in multiple tables
Try this
$orderNumber = (int)$_GET['orderNumber'];
Then where :ordernumber is put $orderNumber
Then execute

php pdo selecting from multiple tables with more than one where clauses

I am new to PHP PDO and converting some regular MySQL queries to work with PDO.
The query below when tested in phpMyAdmin works great when the assigned values replaced the current placeholders in the SQL statement. But when I configure it to work as it is now with PDO, it does not produce any results or errors. Can someone please tell me or show me what is it that I am doing wrong?
Someone told me that I cannot pass parameters as references in the array.
And if correct, what is the best way for creating a solution and by using only the user ID passed through to the variable $uid. Thanks.
<p>// For testing</p>
<pre>$uid = 1;</pre>
<p> </p>
<pre>$array = array(
':uId' => ''.$uid.'',
':aId' => 'u.user_id',
':gID' => 'a.group_id',
':eID' => 'a.entry_id',
':pID' => 'a.permit_id'
);</pre>
// create the sql for qd_user_usam table
$sql = "SELECT u.user_id, a.acl_id, g.group_name, e.entry_level, p.permit_level
FROM qd_users as u, qd_users_acl as a, qd_users_group as g, qd_users_entry as e, qd_users_permission as p
WHERE u.user_id = :uID
AND a.acl_id = :aID
AND g.group_id = :gID
AND e.entry_id = :eID
AND p.permit_id = :pID";
<p>try
{</p>
<p>// Build the database PDOStatement</p>
<pre>$_stmt = $this->_dbConn->prepare($sql);</pre>
<pre>$_stmt->execute($array);</pre>
<pre>}
catch(PDOException $e)
{</pre>
<pre>$this->_errorMessage .= 'Error processing user login access. <br /> Line #'.__LINE__ .' '.$e ;</pre>
<pre>die($this->_errorMessage);
}</pre>
<pre>$results = $_stmt->fetchAll(PDO::FETCH_ASSOC);</pre>
<pre>return $results;</pre>
<pre>$results = null;</pre>
<pre>$this->_dbConn = null;</pre>
You take prepared statements wrong.
Thy have to be used not to represent whatever value in the query, but dynamically added data only.
While a.group_id is a column name and have to be written as is, without prepared statements.
// For testing
$uid = 1;
// create the sql for qd_user_usam table
$sql = "SELECT u.user_id, a.acl_id, g.group_name, e.entry_level, p.permit_level
FROM qd_users as u, qd_users_acl as a, qd_users_group as
g, qd_users_entry as e, qd_users_permission as p
WHERE u.user_id = ?
AND a.acl_id = u.user_id
AND g.group_id = a.group_id
AND e.entry_id = a.entry_id
AND p.permit_id = a.permit_id";
$_stmt = $this->_dbConn->prepare($sql);
$_stmt->execute(array($uid));
The problem is that you're trying to write your JOINs implicitly by binding the joined columns as parameters, which would not work. The parameters can not reference another column; they are seen as strings in this case. If you rewrite the query like this it should fix the JOIN problem:
SELECT u.user_id, a.acl_id, g.group_name, e.entry_level, p.permit_level
FROM qd_users AS u
JOIN qd_users_acl AS a ON (u.user_id = a.acl_id)
JOIN qd_users_group AS g ON (g.group_id = a.group_id)
JOIN qd_users_entry AS e ON (e.entry_id = a.entry_id)
JOIN qd_users_permission AS p ON (p.permit_id = a.permit_id)
WHERE u.user_id = :uID

inner join wont work with mysqli prepared statement in php

I can't seem to get this statement or statements alike to work with prepared queries, the code works just fine below:
$DBH = getDBH();
$stmt = $DBH->prepare("SELECT a.id, a.title, a.photo FROM tag t INNER JOIN tag_reference atx ON t.tag_id = atx.tag_id
INNER JOIN articles a
ON atx.article_id = a.id
WHERE t.tag_name = 'example'");
$stmt->execute();
$stmt->bind_result($id,$title,$photo);
$stmt->fetch();
but when I change t.tag_name = '?' it gives me an error that the amount of parameters do not match. This is the statement that does not work.
$DBH = getDBH();
$stmt = $DBH->prepare("SELECT a.id, a.title, a.photo FROM tag t INNER JOIN tag_reference atx ON t.tag_id = atx.tag_id
INNER JOIN articles a
ON atx.article_id = a.id
WHERE t.tag_name = '?'");
$stmt->bind_param('s',$example);
$stmt->execute();
$stmt->bind_result($id,$title,$photo);
$stmt->fetch();
Can anyone please help?
The placeholder ? does not work if enclosed in single quotes. In this case the SQL tokenizer will catch it as literal string.
Change it to:
WHERE t.tag_name = ? ");
When using placeholders, do you need to use quotes? Most placeholder languages I've used don't.
WHERE t.tag_name = ?"

Categories