如何在 Laravel 中导入具有各种模型(和子数据/模型)的单个 excel 文件/工作表?
Posted
技术标签:
【中文标题】如何在 Laravel 中导入具有各种模型(和子数据/模型)的单个 excel 文件/工作表?【英文标题】:How to import a single excel file/sheet with various Models (and sub-data/models) in Laravel? 【发布时间】:2019-01-10 13:42:40 【问题描述】:根据标题,我在每一行中都有一个包含数据(父/子)的 Excel 文件。 Laravel Excel 网站展示了如何导入,假设每行有一个模型 - 但是如何导入子数据? https://laravel-excel.maatwebsite.nl/3.1/imports/
例如“伪”架构:
Schema::create('students', function (Blueprint $table)
$table->increments('id')->unsigned()->index();
$table->string('student_code',16);
$table->string('student_name',64);
$table->string('student_surname',64);
);
Schema::create('student_courses', function (Blueprint $table)
$table->increments('id')->unsigned()->index();
$table->integer('student_id')->unsigned()->index();
$table->string('course', 32);
$table->date('start_date');
$table->date('end_date');
$table->timestamps();
);
Schema::create('student_contacts', function (Blueprint $table)
$table->increments('id')->unsigned()->index();
$table->integer('student_id')->unsigned()->index();
$table->string('contact_name', 32);
$table->string('contact_number', 32);
$table->timestamps();
);
例如文件:students.xlsx
Student Code | Student Name | Student Surname | Course | Course Start Date | Course End Date | Contact Person | Contact Numbers
ABC1 | Arnold | Clarp | C++ | 2019-01-01 | 2019-12-01 | Boogle | 555-111-222
DEF2 | Delta | Flork | English | 2019-01-02 | 2019-12-02 | Google | 555-111-333
GHI3 | Goblin | Clark | Science | 2019-01-03 | 2019-12-03 | Foogle | 555-111-444
假设我的导入代码:
class StudentsImport implements ToModel, WithStartRow
/**
* @param array $row
*
* @return \Illuminate\Database\Eloquent\Model|null
*/
public function model(array $row)
return new Student([
'student_code' => $row[1],
'student_name' => $row[2],
'student_surname' => $row[3],
]);
/**
* @return int
*/
public function startRow(): int
return 2;
我实际上会在哪里插入“儿童”课程/联系人数据的导入? 我猜不是'返回一个新学生' - 我实际上会先将它分配给一个变量,然后再导入它?这是正确的方法吗? 例如:
public function model(array $row)
$student = new Student([
'student_code'=> $row[1],
'student_name'=> $row[2],
'student_surname'=> $row[3],
])
$student->courses()->create([
'course'=>$row[4],
'start_date'=>$row[5],
'end_date'=>$row[6]
]);
$student->contacts()->create([
'contact_name'=>$row[7],
'contact_number'=>$row[8]
]);
return $student;
//实际代码,不再是“伪”:
$student = new Student([
'bursary_provider_id' => 1,
'bursary_provider_reference' => 'xxx',
'student_name' => $row[1],
'student_initials' => $row[3],
'student_surname' => $row[2],
'passport_number' => $row[7],
'passport_expiration' => \phpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($row[9]),
'country_id' => 7,
'id_number' => $row[6],
'status' => $status,
'notes' => $row[5]
]);
if (isset($row[10]))
$student->visas()->create([
'country_id' => 201,
'visa_reference_number' => $row[10],
'visa_expiration_date' => \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($row[11])
]);
错误(它没有通过父 id)
SQLSTATE[23000]:违反完整性约束:1048 列“student_id”不能为空(SQL:插入student_visas
(country_id
、visa_reference_number
、visa_expiration_date
、student_id
、updated_at
、@ 987654333@) 值 (201, ABCHFV4, 2019-12-31 00:00:00, , 2019-01-11 08:03:06, 2019-01-11 08:03:06))
【问题讨论】:
应该可以。你遇到什么麻烦了吗? 我是 Laravel 菜鸟,我不确定这样做的正确方法,所以还没有完成这个过程 - 想确保我做得正确...... 检查我的编辑 ^ 我可以确认它实际上不起作用 - 父 ID 没有通过... 您在student_visas
中有一个不能为空的列student_id
。我们可以看到Student
和StudentVisa
之间的关系定义吗? :)
我的理解是父ID为空,因为这个阶段student实际上还没有被插入到数据库中。 Laravel Excel 似乎只在最后插入。与我的关系无关 - 虽然为了清楚起见,我确实有一个外键设置。
【参考方案1】:
您收到错误是因为学生尚未写入数据库,因此没有为新学生实例分配 id。如果您使用集合,则数据会立即写入数据库。在模型函数中你可以使用
$student=Student::Create(['bursary_provider_id' => 1,
'bursary_provider_reference' => 'xxx',
'student_name' => $row[1],
'student_initials' => $row[3],
'student_surname' => $row[2],
'passport_number' => $row[7],
'passport_expiration' => \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($row[9]),
'country_id' => 7,
'id_number' => $row[6],
'status' => $status,
'notes' => $row[5]]);
这会将学生写入数据库并生成必要的 ID。不过我不确定这会如何影响性能。
【讨论】:
【参考方案2】:答案(不要问我为什么,因为现阶段的文档很差)是使用集合。
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;
而不是 ToModel:
public function collection(Collection $rows)
它不会“返回”任何东西。除了这些更改之外,在 OP 中使用完全相同的代码可以按预期工作。
【讨论】:
以上是关于如何在 Laravel 中导入具有各种模型(和子数据/模型)的单个 excel 文件/工作表?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Laravel 项目中导入和使用 vue-good-table Vue 组件
如何使用 laravel 5.7 和 vue JS 在 mysql 中导入 excel 文件