Как и большинство вещей, ответ «зависит от».
Прежде чем говорить о производительности, более важным аспектом является ремонтопригодность кода и ограничение async
/ await
vs raw Promise
.
async
/ await
- отличный способ выполнить асинхронный код последовательно, в то время как Promise
позволяет одновременно запускать асинхронный код.
async function foo() {
const a = await backend.doSomething()
const b = await backend.doAnotherThing()
return a + b
}
В приведенном выше коде backend.doAnotherThing()
не будет выполняться до тех пор, пока backend.doSomething()
не вернется. С другой стороны:
function foo() {
Promise.all([backend.doSomething(), backend.doAnotherThing()])
.then(([a, b]) => {
return a + b
})
}
выполнит оба вызова и дождитесь завершения обоих.
Как вы упомянули о преимуществах async
/ await
, I лично использовать его широко. За исключением случаев, описанных выше.
Если вам нужна производительность и вам, разница в производительности между async
/ await
и Promise
важнее, чем преимущество чтения async
/ await
по Promise
, всеми средствами идти вперед.
Пока это сознательный выбор, вы должны быть в порядке.
PDO не очень хорош с такими вещами. Вам нужно создать строку с вопросительными знаками динамически и вставить в запрос.
$in = str_repeat('?,', count($in_array) - 1) . '?';
$sql = "SELECT * FROM my_table WHERE my_value IN ($in)";
$stm = $db->prepare($sql);
$stm->execute($in_array);
$data = $stm->fetchAll();
Если в запросе есть другие заполнители, вы можете использовать следующий подход (код берется из моего PDO tutorial ):
Вы можете использовать функцию array_merge()
, чтобы объединить все переменные в один массив, добавив другие переменные в виде массивов в том порядке, в каком они появляются в вашем query:
$arr = [1,2,3];
$in = str_repeat('?,', count($arr) - 1) . '?';
$sql = "SELECT * FROM table WHERE foo=? AND column IN ($in) AND bar=? AND baz=?";
$stm = $db->prepare($sql);
$params = array_merge([$foo], $arr, [$bar, $baz]);
$stm->execute($params);
$data = $stm->fetchAll();
Если вы используете именованные заполнители, код будет немного сложнее, так как вам нужно создать последовательность именных заполнителей, например :id0,:id1,:id2
. Таким образом, код будет выглядеть следующим образом:
// other parameters that are going into query
$params = ["foo" => "foo", "bar" => "bar"];
$ids = [1,2,3];
$in = "";
foreach ($ids as $i => $item)
{
$key = ":id".$i;
$in .= "$key,";
$in_params[$key] = $item; // collecting values into key-value array
}
$in = rtrim($in,","); // :id0,:id1,:id2
$sql = "SELECT * FROM table WHERE foo=:foo AND id IN ($in) AND bar=:bar";
$stm = $db->prepare($sql);
$stm->execute(array_merge($params,$in_params)); // just merge two arrays
$data = $stm->fetchAll();
К счастью, для названных заполнителей нам не обязательно следовать строгий порядок, поэтому мы можем объединить наши массивы в любом порядке.
Я только что столкнулся с этой проблемой и закодировал небольшую обертку. Это не самый красивый или лучший код, я уверен, но он может помочь кому-то, вот он:
function runQuery(PDO $PDO, string $sql, array $params = [])
{
if (!count($params)) {
return $PDO->query($sql);
}
foreach ($params as $key => $values) {
if (is_array($values)) {
// get placeholder from array, e.g. ids => [7,12,3] would be ':ids'
$oldPlaceholder = ':'.$key;
$newPlaceholders = '';
$newParams = [];
// loop through array to create new placeholders & new named parameters
for($i = 1; $i <= count($values); $i++) {
// this gives us :ids1, :ids2, :ids3 etc
$newKey = $oldPlaceholder.$i;
$newPlaceholders .= $newKey.', ';
// this builds an associative array of the new named parameters
$newParams[$newKey] = $values[$i - 1];
}
//trim off the trailing comma and space
$newPlaceholders = rtrim($newPlaceholders, ', ');
// remove the old parameter
unset($params[$key]);
// and replace with the new ones
$params = array_merge($params, $newParams);
// amend the query
$sql = str_replace($oldPlaceholder, $newPlaceholders, $sql);
}
}
$statement = $PDO->prepare($sql);
$statement->execute($params);
return $statement;
}
Например, передавая их в:
SELECT * FROM users WHERE userId IN (:ids)
array(1) {
["ids"]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}
Становится:
SELECT * FROM users WHERE userId IN (:ids1, :ids2, :ids3)
array(3) {
[":ids1"]=>
int(1)
[":ids2"]=>
int(2)
[":ids3"]=>
int(3)
}
Это не пуленепробиваемый, но, как единственный разработчик для моих потребностей, он отлично работает, пока все равно.
Поскольку PDO, похоже, не дает хорошего решения, вы можете также рассмотреть возможность использования DBAL, который в основном следует API PDO, но также добавляет некоторые полезные функции http://docs.doctrine-project.org/ project / doctrine-dbal / ru / latest / reference / data-retrieval-and-manipulation.html # list-of-parameters-conversion
$stmt = $conn->executeQuery('SELECT * FROM articles WHERE id IN (?)',
array(array(1, 2, 3, 4, 5, 6)),
array(\Doctrine\DBAL\Connection::PARAM_INT_ARRAY)
);
Возможно, есть и другие пакеты там, которые не добавляют сложности и не скрывают взаимодействия с базой данных (как и большинство ORM), но в то же время облегчают небольшие типичные задачи.
Подстановка переменных в подготовленных инструкциях PDO не поддерживает массивы. Это один на один.
Вы можете обойти эту проблему, создав необходимое количество заполнителей на основе длины массива.
$variables = array ('1', '2', '3');
$placeholders = str_repeat ('?, ', count ($variables) - 1) . '?';
$query = $pdo -> prepare ("SELECT * FROM table WHERE column IN($placeholders)");
if ($query -> execute ($variables)) {
// ...
}
Как я понимаю, это потому, что PDO будет рассматривать содержимое $ in_values как отдельный элемент и будет вполне соответствующим образом. PDO увидит 1,2,3 как одну строку, поэтому запрос будет выглядеть примерно как
SELECT * FROM table WHERE my_value IN ("1,2,3")
Вы может подумать, что изменение impode будет иметь кавычки и запятые, чтобы исправить это, но это не будет. PDO увидит цитаты и изменит, как она цитирует строку.
Что касается того, почему ваш запрос соответствует первому значению, у меня нет объяснений.