0

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());
?>

2 Answers 2

1

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);
Sign up to request clarification or add additional context in comments.

5 Comments

$x is being assigned in the foreach loop... so it should be the same as $countries[$k]
@TimMorton yes, it's value is the same (which is why swapping to bindValue will work) but bindParam forms a link to the variable, so at the end of the loop, all the bound parameters will point to the same thing, and all get the same value.
Wow, it worked. Though I don't understand why my code in the question doesn't work. $x should have the exact same value as $countries[$k].
@Aman see my previous comment to Tim Morton. bindParam forms a link to the variable, so all your parameters are bound to $x, and when you execute the query it has the last value in the countries array, meaning you are effectively ignoring the other vaues in the array.
@Nick Thanks for explaining. Reference instead of value... I completely missed any clues pointing to that.
1

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)

2 Comments

What About for the IN statement?
Cannot use bindParam with IN clause. Can use bindValue instead or inject in sql u.country NOT IN ('" . implode("','", $countries) . "')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.