Запись данных в БД из массива

Подскажите как реализовать запись в базу данных значений из ассоциативного массива.

Нужно чтобы цикл проходил по всему массиву и записывал данные в БД

Использовал:

$arr = ["red" => "красный", "blue" => "синий", "green" => "зеленый"];  // массив 
$id_repair = '12'; // ID который необходим для записи в таблицу БД

function uploadCreateRepair($id_repair,$arr){
foreach ($arr as $value) {
    global $pdo;
    $sql = "INSERT INTO `repairs_part` (`id_repair`, `part`, `text`, `name_img`) VALUES ($id_repair, '1', $value, '')";
    $query = $pdo->prepare($sql);
    $query->execute();
    dbCheckError($query);
    return $pdo->lastInsertId();
}

}

Записывается только первая строка массива и дальше не идет перебор. Выяснил, что цикл перестает работать после $sql, какова причина или как сделать более человечную функцию ?


Ответы (1 шт):

Автор решения: Ипатьев

Код в вопросе, конечно, дурацкий, но сам по себе вопрос важный и полезный. И не всякий критикующий в состоянии написать несложный код, который здесь требуется.

1. Подготовленные запросы

Но перед тем как писать код, надо запомнить, что на пресс-конференции к звездам надо приходить запросы надо выполнять подготовленными. Это означает, что слова prepare и execute надо использовать по назначению, а не просто рисовать их для красоты.

  • В prepare идет запрос без переменных. Вместо них должны быть знаки вопроса.
  • А сами переменные должны передаваться в execute, в виде массива.

И тогда у нас никогда не будет ни одной ошибки, вызванной передаваемыми в запрос данными, не говоря уже об SQL инъекциях.

2. Множественный insert

Эффективнее всего производить вставку одним запросом, вида

INSERT INTO table (col1, col2, col3) VALUES (?,?,?),(?,?,?),(?,?,?)...

То есть вся задача сводится к несложному коду, который из двумерного массива построит строку из "вагончиков" вида (?,?,?),(?,?,?). Причем в нормальном варианте все значения для вставки уже есть в массиве, а не собираются с миру по нитке. И мы напишем код для такого случая.

Если количество вставляемых значений заранее известно, то "вагончики" для VALUES можно клепать вручную, простым циклом

$values = "";
foreach($data as $row)
{
    $values .= $values ? "," : ""; // перед первым вагончиком запятую не ставим
    $values .= "(?,?)";
}

Если же количество колонок может меняться, то можно написать чуть более интеллектуальный код, который поддерживает динамическое количество колонок для вставки

$chunk = str_repeat('?,', count($data[0]) - 1) . '?';
$values = str_repeat("($chunk),", count($data) - 1) . "($chunk)";    

Дальше останется только подставить полученную строку из скобочек с вопросиками в запрос, и выполнить его ("схлопнув" исходный двумерный массив в одномерный для execute)

$sql = "INSERT INTO `repairs_part` (`id_repair`, `part`, `text`, `name_img`) VALUES ";
$sql .= $values;
$conn->prepare($sql)->execute(array_merge(...$data));

Если же, как у автора вопроса, массив одномерный, то массив для вставки нужно будет собирать вручную

$values = "";
$params = [];
foreach($data as $item)
{
    $values .= $values ? "," : ""; // перед первым вагончиком запятую не ставим
    $values .= "(?,?)";
    array_push($params, $id_repair, $item);
}
$sql = "INSERT INTO `repairs_part` (`id_repair`, `part`, `text`, `name_img`) VALUES ";
$sql .= $values;
$conn->prepare($sql)->execute($params);
→ Ссылка