如何:导入到 laravel 时灵活的数据映射?

How to: flexible data mapping on import to laravel?

我目前正在尝试为我们的一个应用程序实施灵活且易于使用的导入服务。该应用程序在后台运行 Laravel,目前我们使用的是固定的 csv-import。
这意味着:客户需要提供根据我们的指南格式化的 csv 文件,以匹配我们数据库中的列。

现在这个工作正常,但肯定不灵活或不直观。

现在我正在尝试提出一个更好的解决方案(例如 MailChimp 使用的 csv 导入向导)。

但目前我完全迷路了。我不知道如何使用像 https://github.com/ddeboer/data-import 这样的库来实现具有以下功能的解决方案:

我的主要挑战是接收用户的数据并让他们自己选择映射。使用像 ddeboer/data-import 这样的库时如何拆分这个过程?

还应该考虑到,数据库可能会在接下来的几个月内发生变化,如果可能的话,我不想回到我的源代码来实现这些变化。

如果有人能指出正确的方向,我将不胜感激。

谢谢!

我们提出的解决方案如下所示:

我们使用多条路线:

1. /import GET
2. /import POST
3. /import-map GET
4. /import-map POST

1) 呈现带有用于上传 csv 文件的文件输入的视图。

2) 将文件上传到一个临时路径,以便我们可以使用它。该路径保存到会话中,并由 3) 使用以打开文件。由于我们必须处理许多不同的编码,上传功能做了一些讨厌的事情 decoding/encoding 以获得有效的 utf8 文件。

/**
 * Upload the given file to a temp path
 *
 * @param Filesystem $filesystem
 * @param $filePath
 * @return string
 */
public function upload(Filesystem $filesystem, $filePath)
{
    $path = str_random(20);
    $fullPath = public_path('temp/' . $path . '.csv');

    if ( ! mb_detect_encoding($filesystem->get($filePath), mb_detect_order(), true))
        $filesystem->put($filePath, chr(239) . chr(187) . chr(191) . utf8_encode($filesystem->get($filePath)));

    $filesystem->move($filePath, $fullPath);

    return $path;
}

3) 呈现导入映射视图。该文件加载了会话中的值。如果没有找到会话数据,用户将被重定向到 1).

<th>
    <select name="col-name[{{ $i }}]" data-eq="{{ $i }}" class="form-control">
        <option value="">Datenbankspalte auswählen</option>
        @foreach($tableColumns as $key => $value)
            <option value="{{ $key }}">{{ $value }}</option>
        @endforeach
    </select>
</th>

4) 负责导入:

/**
 * Import the uploaded file one row at a time
 *
 * @param $input
 * @return bool
 * @throws \Exception
 */
public function import(array $input)
{
    if ( ! array_key_exists('campaign_id', $input))
        throw new Exception();

    $columns = array_filter($input['col-name']);

    if (empty($columns))
        throw new Exception();

    $this->openFile($input['csvPath']);

    foreach ($this->readCsv(null, (array_key_exists('headers', $input) ? 1 : 0)) as $row)
    {
        $address = new $this->address;

        foreach ($columns as $key => $value)
        {
            if ($value == '')
                continue;

            $address->$value = $row[$key];
        }
        $address->save();
        $address->campaigns()
                ->attach($input['campaign_id'], ['client_id' => auth()->user()->client_id, 'user_id' => (array_key_exists('user_id', $input) ? $input['user_id'] : 0)]);
    }

    return true;
}

这并不太难,是吗:-)