Нужна помощь в создании аналогичной функциональности для импорта и сопоставления CSV, похожей на Mailchimp.

Что я пытаюсь сделать, так это загрузить CSV продуктов, получить заголовки и создать инструмент сопоставления, который позволит пользователю сопоставлять заголовки CSV с полями, в которые они должны быть импортированы. Я думаю, мне нужно получить значения столбца, а не значения строки.

Mailchimp в настоящее время имеет эту очень классную функциональность, как, я уверен, и все другие крупные игроки в почтовом маркетинге. После импорта система перечисляет имя каждого столбца и позволяет пользователю выбрать, с чем его сопоставить со своими встроенными столбцами.

Я исследовал несколько различных ранее существовавших решений, и все они кажутся ошибочными, и мне просто придется создать свое собственное решение.

В настоящее время я использую PHP/MySQL. Любая помощь или совет будут очень признательны!


person AllSystemsDown    schedule 23.05.2014    source источник
comment
Можете ли вы привести краткий пример того, как выглядит CSV? Просто чтобы уточнить, вы пытаетесь взять CSV и сопоставить (вставить) все его данные в таблицу MySQL, где пользователь явно определил соответствующие заголовки CSV и столбцы базы данных?   -  person Shane Reeves    schedule 23.05.2014
comment
Привет Шейн, спасибо за ответ. CSV довольно стандартный, содержит около 12 заголовков столбцов и различные типы данных для каждой ячейки. Чтобы ответить на ваш вопрос, я хотел бы сделать промежуточный шаг после того, как пользователь загрузит CSV, где он может выбрать, в какую таблицу идет каждый столбец данных из CSV. Затем отправляет его для вставки в базу данных. Я надеюсь, что это полностью отвечает на ваш вопрос. Я попытался прикрепить скриншот из Mailchimp, но у меня сейчас недостаточно очков репутации! Спасибо!   -  person AllSystemsDown    schedule 23.05.2014
comment
Извините за долгий ответ, я постараюсь собрать что-нибудь сегодня вечером, чтобы вы заработали, я возвращаюсь домой с работы. :)   -  person Shane Reeves    schedule 24.05.2014


Ответы (1)


Основываясь на том, что вы мне предоставили, я собрал следующий класс PHP, который, надеюсь, должен предоставить вам необходимую функциональность. Нижняя часть кода демонстрирует использование малого класса.

<?php
class CSVtoSQL {
    private $filePath, $csvData;

    public function __construct($filePath) {
        $this->filePath = $filePath;
    }

    public function readDataIn() {
        $file = fopen($this->filePath, 'r');
        $data = fread($file, filesize($this->filePath));

        // Split CSV line by line.
        $lines = explode("\n", $data);

        // Split each line by commas to extract each value.
        for ($i = 0; $i < sizeof($lines); $i++) {
            $this->csvData[$i] = explode(',', $lines[$i]);
        }

        fclose($file);

        // Returns true if we managed to read data, false if we didn't.
        return (sizeof($this->csvData) > 0);
    }

    public function getHeadings() {
        if (sizeof($this->csvData) > 0) {
            // The first index of csvData has all the headings.
            return $this->csvData[0];
        }
        else {
            return null;
        }
    }

    public function pushToDatabase($con, $tableName, $columns) {
        $createColumnQuery = '';
        $insertQuery = 'INSERT INTO ' . $tableName . ' (';

        // Build column section of query.
        foreach ($columns as $column) {
            $createColumnQuery .= $column['name'] . ' ' . $column['type'] . ',';
        }

        // Remove trailing comma.
        $createColumnQuery = rtrim($createColumnQuery, ',');

        // Create table.
        $con->query('CREATE TABLE ' . $tableName . ' (' . $createColumnQuery . ')');

        // Create insert query template.
        foreach ($columns as $column) {
            $insertQuery .= $column['name'] . ',';
        }

        // Remove trailing comma.
        $insertQuery = rtrim($insertQuery, ',');

        // Insert values using our insertQuery string which looks like: "INSERT INTO <<table name>> (<<column 1>>, <<column 2>>"
        // Also skip the first line as that has the headings.
        for ($i = 1; $i < sizeof($this->csvData); $i++) {
            $values = '';

            foreach($this->csvData[$i] as $value) {
                $values .= '\'' . $value . '\',';
            }

            // Remove trailing comma.
            $values = rtrim($values, ',');
            $con->query($insertQuery . ') VALUES (' . $values . ')');
        }
    }
}

$csv = new CSVtoSQL('test.csv');
$csv->readDataIn();
var_dump($csv->getHeadings());
$con = new mysqli('127.0.0.1', 'root', '', 'testdb');
$columns = array(array('name'=>'col1', 'type'=>'VARCHAR(256)'),
                array('name'=>'col2', 'type'=>'VARCHAR(256)'),
                array('name'=>'col3', 'type'=>'VARCHAR(256)'));
$csv->pushToDatabase($con, 'test_table', $columns);
?>

При создании нового объекта класса CSVtoSQL необходимо передать путь к CSV-файлу (он может быть относительным или абсолютным). Затем вызовите процедуру readDataIn(), чтобы открыть CSV, извлечь строки и сохранить их в объекте. Затем вы можете дополнительно получить массив заголовков, найденных в CSV, вызвав getHeadings(). Это будет полезно для вас, когда вы хотите подсказать пользователю, какие столбцы базы данных они хотят сопоставить с каждым заголовком CSV. Наконец, вызовите pushToDatabase() и укажите объект подключения MySQLi, имя таблицы и данные столбца, как показано.

Для меня тривиально написать для вас форму загрузки, но этот класс должен помочь решить вашу проблему.

Удачи!

person Shane Reeves    schedule 24.05.2014
comment
Шейн, спасибо! Я ценю ваши усилия, чтобы сделать эту работу. Я пытаюсь использовать это сейчас. - person AllSystemsDown; 28.05.2014
comment
Не беспокойтесь, это не должно быть слишком сложно реализовать с помощью некоторых простых HTML-форм. Удачи! - person Shane Reeves; 29.05.2014