使用Eloquent模型ID交换数组值

时间:2016-10-25 13:50:17

标签: php csv laravel-5 laravel-5.3

我需要创建一个导入CSV文件并导入数据库中所有内容的导入方法。

我已经使用Laravel的一个CSV插件完成了解析,它完美地为我提供了一系列值设置为:

[
    'col1_name' => 'col1 value',
    'col2_name' => 'col2 value',
    'col3_name' => 'col3 value,
    '...' => '...'
]

这也很完美,因为所有列名都适合我的模型,这使得数据库插入变得轻而易举。

但是 - 很多列值都是我想要设置为单独的表/关系的字符串。例如,一列包含项目制造商的名称,我在我的数据库中设置了制造商表。

我的问题是 - 通过导入的CSV以及使用关系表中相应ID交换字符串的简单方法是什么,使其与我的数据库设计兼容?

会导致导入行的东西:

[       
    'manufacturer' => 'Dell',
]

成:

[       
    'manufacturer' => '32',
]

我知道我可以做一个foreach循环,将所需的值与关系模型中的值进行比较,但我确信这样做更容易,更干净。

1 个答案:

答案 0 :(得分:0)

我认为没有任何"很好"这样做的方式 - 您需要查找"制造商"的每个值。 - 问题是,你会运行多少次查询?

您需要在此处考虑的是您将从CSV文件中导入的行数。

你有几个选择。

1)逐个查询

我假设您无论如何都会循环遍历CSV文件的每一行,然后制作新模型?在这种情况下,您可以在此处添加额外的数据库调用;

$model->manufacturer_id = Manufacturer::whereName($colXValue)->first()->id;

(您显然需要在此处插入自己的支票等以确保制造商存在)

这种方法是相对较小的数据集,但是,如果你要导入很多很多行,它可能会因为很多可能不必要的数据库调用而变得迟​​钝。

2)映射所有制造商

另一个选择是在循环CSV行之前创建所有制造商的本地地图;

$mappedManufacturers = Manufacturer::all()->pluck('id', 'name');

这将使$mappedManufacturers一系列制造商以name为关键字,id作为值。这样,当您构建模型时,您可以这样做;

$model->manufacturer_id = $mappedManufacturers[$colXValue];

这种方法也没问题,除非你有成千上万的制造商!

3)在哪里 - 然后重新循环

另一个选择是在循环CSV行时建立制造商名称列表,使用1 whereIn查询进入数据库,然后重新循环模型以填充制造商ID。

因此,在初始循环CSV中,您可以临时设置属性以存储制造商的名称,同时将其添加到另一个阵列;

$models = collect(); $model->..... = ....; $model->manufacturer = $colXValue; $models->push($colXValue);

然后你最终得到了一系列模型。然后,您只查询数据库中出现的制造商:

$manufacturers = Manufacturer::whereIn('name', $models->lists('manufacturer'))->get()->keyBy('name')->toArray();

这将为您提供一系列制造商,其密码为name

然后,您再次遍历$models集合,使用地图指定正确的制造商ID;

$model->manufacturer_id = $manufacturers[$model->manufacturer];

希望这能为您提供一些如何实现这一目标的想法。我说解决方案主要取决于你的使用案例 - 如果这是一个重要的问题 - 我肯定会排队并且很想使用选项1! :P