PDO bindParam not working in IN binding for sql query - php

I'm trying to get some videos according to some attributes (age, year, countries). For some reason, even though I'm binding parameters to the query properly and have specified the query properly (u.country NOT IN ($countries_count)), I still get results for the country = U.S.A. Is there something work with my bindParam. Please Help.
<?php
$parameters = json_decode(file_get_contents('php://input'), true);
$age = $parameters["age"];
$year = $parameters["year"];
$countries = sizeof($parameters["countries"]) == 0 ? array("0") : $parameters["countries"];
$countries_count = implode(",", array_fill(0, sizeof($countries), "?"));
$sql = "SELECT
v.title, u.name
FROM
video AS v JOIN user AS u ON v.id_user = u.id
WHERE
u.age <= ? AND YEAR(v.upload_date) >= ? AND
u.country NOT IN ($countries_count);";
$connection = new PDO("mysql:host=localhost;dbname=data_base", "root", "");
$statement = $connection->prepare($sql);
$statement->bindParam(1, $age, PDO::PARAM_INT);
$statement->bindParam(2, $year, PDO::PARAM_INT);
foreach ($countries as $k => $x) {
$statement->bindParam($k+3, $x, PDO::PARAM_STR);
}
$statement->execute();
echo json_encode($statement->fetchAll());
?>

Your problem is that you are binding all the IN parameters to the same variable ($x) so they all end up with the same value. You can work around that by either changing to bindValue or by binding to the actual array value I.e.
$statement->bindParam($k+3, $countries[$k], PDO::PARAM_STR);

Change bindParam to bindValue
If you want to use bindParam, change your sql to
u.age <= :age and
YEAR(v.upload_date) >= :year
...
Then bind param:
->bindParam(':age', $age)
->bindParam(':year', $year)

Related

two condition for where Clause in SQL

I want execute a sql query with my php code but it is wrong and I don't know what is my problem!
$end_type = $executed[end_type];
$start_type = $executed[start_type];
$sql = "SELECT * FROM `wants` WHERE ((`car`=? AND $start_type=? AND $end_type=?) OR (`car`=? AND $start_type=? AND $end_type='all'))";
$query = $con->prepare($sql);
$query->bindValue(1, $executed[car]);
$query->bindValue(2, $executed[start_place]);
$query->bindValue(3, $executed[end_place]);
$query->execute();
$results = $query->fetchall();
sendmsg($user_id, $results);
sendmsg is my massage sender function and it don't return any array even an empty array!
why? what in my solution?
The main issue here seems to be that you have five ? placeholders in your prepared statement, but are only binding three values. There might be some way to recycle binding values in PHP, but in this case I would rephrase your query as:
SELECT *
FROM wants
WHERE car = ? AND start_type = ? AND end_type IN (?, 'all');
Updated PHP code:
$sql = "SELECT * FROM wants WHERE car = ? AND start_type = ? AND end_type IN (?, 'all')";
$query = $con->prepare($sql);
$query->bindValue(1, $executed[car]);
$query->bindValue(2, $executed[start_place]);
$query->bindValue(3, $executed[end_place]);
$query->execute();
$results = $query->fetchall();

PDO prepared statement bind parameters once for different queries

I am using PDO prepared statements to execute two queries:
SELECT count(*) FROM vocabulary WHERE `type` = :type AND `lesson` = :lesson;
SELECT * FROM vocabulary WHERE `type` = :type AND `lesson` = :lesson limit 100;
The first query to get the count works as expected and i get the row count.
$stmt = $this->connection->prepare($sql);
foreach ($params as $key => $value)
$stmt->bindValue(":" . $key, $value, PDO::PARAM_STR);
$stmt->execute();
$count = $stmt->fetchColumn();
$sql .= " limit $limit;";
$sql = str_replace("count(*)", $columns, $sql);
$stmt = $this->connection->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_CLASS, $class);
But when executing the second query i get:
SQLSTATE[HY093]: Invalid parameter number: no parameters were bound
Therefore, I would like to know, if I have multiple queries where the parameters are exactly the same ,if I need to bind the same parameters again using
foreach ($params as $key => $value)
$stmt->bindValue(":" . $key, $value, PDO::PARAM_STR);
or if there is a way to bind parameters only once.
If I have multiple queries where the parameters are exactly the same, do I need to bind the same parameters again using
Yes, of course.
Parameters are bound to each query, not to PDO or a database globally.
On a side note, with PDO you don't have to bind variables explicitly, so there is a solution to your "problem": just don't bind at all but send your data directly into execute() as it shown in the Dharman's excellent answer
There is no need to modify your SQL like this. Your code basically comes down to this:
$stmt = $this->connection->prepare('SELECT count(*) FROM vocabulary WHERE `type` = :type AND `lesson` = :lesson');
$stmt->execute($params);
$count = $stmt->fetchColumn();
$stmt = $this->connection->prepare('SELECT * FROM vocabulary WHERE `type` = :type AND `lesson` = :lesson limit 100');
$stmt->execute($params);
$result = $stmt->fetchAll(PDO::FETCH_CLASS, $class);

PDO debugging update query using bindValue

I'm using PDO and I can't find what's wrong in there and can't seem to get an error even if PDO's setAttribute is set to.
$fields = $data['fields'];
$cartID = $data['cartID'];
$sql = "UPDATE ShoppingCart
SET shipToSameLocation_shippingLocationID = :shippingLocationID, shipToSameLocation_shippingMethod = :shippingMethod, shipToSameLocation = 1
WHERE cartID = :cartID";
$query = $conn->prepare($sql);
$query->bindValue(':shippingLocationID', $fields['shipToSameLocation_shippingLocationID'], PDO::PARAM_INT);
$query->bindValue(':shippingMethod', $fields['shipToSameLocation_shippingMethod'], PDO::PARAM_STR);
$query->bindValue(':cartID', $cartID, PDO::PARAM_INT);
$query->execute();
Anything wrong in there related to PDO?
Proabaly because you are explicitly saying that the value will be an int but not coercing the post value into and int;
$fields = $data['fields'];
$cartID = (int) $data['cartID'];
$sql = "UPDATE ShoppingCart
SET shipToSameLocation_shippingLocationID = :shippingLocationID, shipToSameLocation_shippingMethod = :shippingMethod, shipToSameLocation = 1
WHERE cartID = :cartID";
$query = $conn->prepare($sql);
$query->bindValue(':shippingLocationID', $fields['shipToSameLocation_shippingLocationID'], PDO::PARAM_INT);
$query->bindValue(':shippingMethod', $fields['shipToSameLocation_shippingMethod'], PDO::PARAM_STR);
$query->bindValue(':cartID', $cartID, PDO::PARAM_INT);
$query->execute();
The same goes for the other values you are binding so cast them to their correct type, or better yet don't use bind value. Personally I have never bothered to bind params or values, I just pass an associative array into PDO.
$locId = (int) $fields['shipToSameLocation_shippingLocationID'];
$method = $fields['shipToSameLocation_shippingMethod'];
$cartId = (int) $data['cartID'];
$params = array(
':shippingLocationID' => $locId ,
':shippingMethod' => $method,
':cartID' => $cartId
);
$query->execute($params);
works for like a charm every time. Most places I work, the other people end up adopting this method because it is so much less trouble to code and to use, but it is up to you.

bindParam PDO PHP

I am having a problem with binding param or value, does anybody knows what wrong?
If i change ? to area it works :-$
$item = 'area';
$query = dbConnectionPDO::getConnect()->prepare( ' SELECT * FROM ? ' );
$query->bindParam(1, $item, PDO::PARAM_STR);
$query->execute();
while($resultId = $query->fetch(PDO::FETCH_ASSOC)){
////
}
Is this a good solution? It works!
$select = 'select * from ' . $item . ' left join ' . $TableName . ' ';
$query = dbConnectionPDO::getConnect()->prepare("$select ON :three = :four");
$query->bindValue(':three', $three, PDO::PARAM_STR);
$query->bindValue(':four', $four, PDO::PARAM_STR);
$query->execute();
while($resultId = $query->fetch(PDO::FETCH_ASSOC)){
////
}
You're trying to bind a table name, not a parameter. I'm not sure you can actually do that.
bindParam works by binding question-mark holders or named parmeters, not a table name.
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->bindParam(1, $calories, PDO::PARAM_INT);
$sth->bindParam(2, $colour, PDO::PARAM_STR, 12);
$sth->execute();
If you're just looking into placeholder "replacement" you can just use sprintf, but be careful since if you'll be doing anything fishy or stupid (like accepting the table name from an external source), it might be leaky.
For example:
$theQ = "SELECT * FROM `%s` LEFT JOIN `%s` ON `%s` = `%s`";
$runQ = sprintf($theQ, 'one', 'two', 'three', 'four');
You need to provide a valid SQL statement where only literals are parametrized. Even if the database driver is dumb enough to accept the query, you'll end up executing something like:
SELECT * FROM 'area'
... which is obviously not what you intended.
You cant parametrize a table name, only parameters.

PDO and alphanumeric strings?

The current error when running this from the command line is "Call to a member function bindParam() on a non-object" which I've worked out to being a problem with the variable $orderPO. Something does not like non-numeric characters which led me to the bindParam PARAM_STR business which does not work either. The database fields are both varchar 50.
My search skills are failing me. I know this must be posted somewhere about a million times but I can't seem to find it. I am completely open to doing this another way if someone has a better idea.
Current attempt code:
try
{
$orderNum = '123456';
$orderPO = '123456-A';
$dbh = new PDO("mysql:host=localhost;dbname=dbname", 'someuser', 'somepass');
$stm = $dbh->prepare("insert into some_table (order_number, order_po)");
$stm->bindParam(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindParam(':order_po', $orderPO, PDO::PARAM_STR);
$stm->execute();
print_r($stm);
print_r($dbh);
$arr = $stm->errorInfo();
print_r($arr);
$stm->closeCursor();
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
In order to bind parameters using PDO, you will need to use placeholders, like this:
$stm = $dbh->prepare("
INSERT INTO `some_table` SET
`order_number` = :order_number,
`order_po` = :order_po
");
$stm->bindParam(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindParam(':order_po', $orderPO, PDO::PARAM_STR);
Notice the inclusion of the : character before the named placeholder. I also added column names to your query.
Read further and see examples: PDO bindParam
The correct syntax is
$stm = $dbh->prepare("insert into some_table (order_number, order_po) VALUES (?, ?)");
$stm->bindParam(1,$orderNum);
$stm->bindParam(2,$orderPO);
include the questions marks, the numbers in the bindParam call refer to which question mark you're binding the parameter to
You are trying to use bindparam, but bind param matches ? not cursors :. You have not included any parameters or values.
Also, you are missing your VALUES statement within the query, which is causing the query to fail. This is why you get the "Call to a member function bindParam() on a non-object"
To use the :value syntax, use bindValue, not bindParam. to use bindParam, switch the :value to ? in your query and number them in order is your execute array.
try
{
$orderNum = '123456';
$orderPO = '123456-A';
$dbh = new PDO("mysql:host=localhost;dbname=dbname", 'someuser', 'somepass');
$stm = $dbh->prepare("insert into some_table (order_number, order_po) VALUES (:order_number, :order_po)");
$stm->bindvalue(':order_number', $orderNum, PDO::PARAM_STR);
$stm->bindvalue(':order_po', $orderPO, PDO::PARAM_STR);
$stm->execute();
print_r($stm);
print_r($dbh);
$arr = $stm->errorInfo();
print_r($arr);
$stm->closeCursor();
$dbh = null;
}
catch(PDOException $e)
{
echo $e->getMessage();
}

Categories