Вставка данных из mysql из CSV с использованием PHP PDO

У меня есть список данных в формате CSV, и мне нужно вставить эти данные в базу данных MySQL. Эти данные должны быть безопасно введены, например, санитария. Итак, я использовал объект PDO для исправления SQL-инъекций. Но он не может получить данные из файла CSV и вставляет нулевые значения.

Вот пример,

<?php
$servername = "localhost";
$username   = "root";
$password   = "";

try {
    $conn = new PDO("mysql:host=$servername;dbname=contact_list",$username,$password);
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    echo "connection successfully";
}
catch(PDOException $e)
{
    echo "connection Failed:" . $e -> getMessage();
}

// Create  CSV to Array function
function csvToArray($filename = '', $delimiter = ',')
{
    if (!file_exists($filename) || !is_readable($filename)) {
        return false;
    }

    $header = NULL;
    $result = array();
    if (($handle = fopen($filename, 'r')) !== FALSE) {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
            if (!$header)
                $header = $row;
            else
                $result[] = array_combine($header, $row);

        }
        fclose($handle);
    }

    return $result;
}

// Insert data into database   

$all_data = csvToArray('contact.csv');
foreach ($all_data as $data) {

    $data = array_map(function($row){
        return filter_var($row, FILTER_SANITIZE_STRING, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
        }, $data);

    $sql = $conn->prepare("INSERT INTO contact 
                (title, first_name,last_name,company_name,date_of_birth,notes) 
        VALUES (:t, :fname, :lname,:cname,:dob,:note)");

    $sql->bindParam(':t', $data[1], PDO::PARAM_STR);
    $sql->bindParam(':fname', $data[2], PDO::PARAM_STR);
    $sql->bindParam(':lname', $data[3], PDO::PARAM_STR);
    $sql->bindParam(':cname', $data[0], PDO::PARAM_STR);
    $sql->bindParam(':dob', $data[4], PDO::PARAM_STR);
    $sql->bindParam(':note', $data[15], PDO::PARAM_STR);
    print_r($data);
    $sql->execute();    
}
?>

Может ли кто-нибудь помочь мне решить эту проблему?


person Sharmi    schedule 23.10.2018    source источник
comment
Можем ли мы увидеть, что в некоторых примерах строк contact.csv все строки имеют длину ‹ 1000?   -  person Jonnix    schedule 23.10.2018
comment
что возвращает print_r($all_data);?   -  person Rotimi    schedule 23.10.2018
comment
Включить отчеты об ошибках php.net/manual/en/function.error-reporting.php и расскажите нам, что показывает.   -  person Funk Forty Niner    schedule 23.10.2018
comment
Вы также можете импортировать CSV напрямую в MySQL: dev.mysql.com /doc/refman/8.0/ru/load-data.html   -  person Dormilich    schedule 23.10.2018
comment
@ Akintunde-Rotimi Я пытался распечатать данные, чтобы увидеть, зацикливаются ли они.   -  person Sharmi    schedule 23.10.2018
comment
@FunkFortyNiner не показывает никаких ошибок.   -  person Sharmi    schedule 23.10.2018
comment
@JonStirling Я изменил параметр на потому, что не хочу давать ограничение значения.   -  person Sharmi    schedule 23.10.2018
comment
@JonStirling Связал мой рассматриваемый образец.   -  person Sharmi    schedule 23.10.2018
comment
Может ли это быть так же просто, как отсутствие заголовков в столбце «Заголовок»?   -  person RiggsFolly    schedule 23.10.2018
comment
А также отсутствующие названия компаний в столбце с названием компании !!!!!!   -  person RiggsFolly    schedule 23.10.2018
comment
@RiggsFolly Да, в любом случае он должен сохраняться в БД с нулевыми значениями, если это не так.   -  person Sharmi    schedule 24.10.2018


Ответы (1)


Если вы посмотрите документацию для array_combine(), вы увидите, что ее целью является построение ассоциативного массива. Вы используете эту функцию в csvToArray(), но позже в своем коде вы пытаетесь получить данные с помощью цифровых клавиш. Я не ожидал, что ты когда-нибудь что-нибудь вставишь.

С другой стороны, вы полностью уничтожаете цель подготовленных утверждений, многократно готовя одно и то же утверждение снова и снова. Подготовьтесь один раз и выполните много раз. Индивидуальная привязка параметров требуется редко, почти во всех случаях вы можете предоставить данные PDOStatement::execute() в виде массива. Также дурным тоном является хранение объектов HTML в базе данных; если вам нужно вывести в HTML, вы выполняете экранирование в этот момент.

Что-то вроде этого должно работать (при необходимости отрегулируйте имена ключей массива).

$all_data = csvToArray('contact.csv');
$sql = $conn->prepare("INSERT INTO contact 
    (title, first_name, last_name, company_name, date_of_birth, notes) 
    VALUES (:t, :fname, :lname,:cname,:dob,:note)");
foreach ($all_data as $data) {
    $params = [
        ":t"     => $data["t"],
        ":fname" => $data["fname"],
        ":lname" => $data["lname"],
        ":dob"   => $data["dob"],
        ":note"  => $data["note"],
    ];
    $sql->execute($params);
}
person miken32    schedule 23.10.2018
comment
Я попробовал этот метод, изменив значение индекса массива, например $data[0],$data[1].... но все же он сохраняет нулевые значения. - person Sharmi; 24.10.2018
comment
Вы читали первый абзац моего ответа? Где я сказал, что вся ваша проблема заключалась в использовании числовых индексов? - person miken32; 24.10.2018