Doctrine - How to bind array to the SQL?
You can't use prepared statements with arrays simply because sql itself does not support arrays. Which is a real shame. Somewhere along the line you actually need to determine if your data contains say three items and emit a IN (?,?,?). The Doctrine ORM entity manager does this for you automatically.
Fortunately, the DBAL has you covered. You just don't use bind or prepare. The manual has an example: https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion
In your case it would look something like:
$sql = "select * from user where id in (?) and status = ?";
$values = [$accounts,'declined'];
$types = [Connection::PARAM_INT_ARRAY, \PDO::PARAM_STR];
$stmt = $conn->executeQuery($sql,$values,$types);
$result = $stmt->fetchAll();
The above code is untested but you should get the idea. (Make sure you use Doctrine\DBAL\Connection;
for Connection::PARAM_INT_ARRAY
)
Note for people using named parameters:
If you are using named parameters (:param
instead of ?
), you should respect the parameter names when providing types. For example:
$sql = "select * from user where id in (:accounts) and status = :status";
$values = ['accounts' => $accounts, 'status' => 'declined'];
$types = ['accounts' => Connection::PARAM_INT_ARRAY, 'status' => \PDO::PARAM_STR];
If you want to stick to the :param
syntax where order does not matter, you have to do a bit of extra work, but I'll show you an easier way to bind the parameters:
// store all your parameters in one array
$params = array(
':status' => 'declined'
);
// then, using your arbitrary array of id's ...
$array_of_ids = array(5, 6, 12, 14);
// ... we're going to build an array of corresponding parameter names
$id_params = array();
foreach ($array_of_ids as $i => $id) {
// generate a unique name for this parameter
$name = ":id_$i"; // ":id_0", ":id_1", etc.
// set the value
$params[$name] = $id;
// and keep track of the name
$id_params[] = $name;
}
// next prepare the parameter names for placement in the query string
$id_params = implode(',', $id_params); // ":id_0,:id_1,..."
$sql = "select * from user where id in ($id_params) and status = :status";
In this case we end up with:
"select * from user where id in (:id_0,:id_1,:id_2,:id_3) and status = :status"
// now prepare your statement like before...
$stmt = $em->getConnection()->prepare($sql);
// ...bind all the params in one go...
$stmt->execute($params);
// ...and get your results!
$result = $stmt->fetchAll();
This approach will also work with an array of strings.