Как импортировать один файл / лист Excel с различными моделями (и субданными / моделями) в Laravel? - PullRequest
0 голосов
/ 10 января 2019

Согласно заголовку, у меня есть один файл Excel, полный данных (родительский / дочерний) в каждой строке. Сайт Laravel Excel показывает, как импортировать, предполагая одну модель на строку - но как импортировать дочерние данные? https://laravel -excel.maatwebsite.nl / 3,1 / импорт /

например, псевдо-схема:

    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])
        ]);

Ошибка (не проходит через родительский идентификатор)

SQLSTATE [23000]: нарушение ограничения целостности: 1048 Столбец 'student_id' не может быть пустым (SQL: вставить в student_visas (country_id, visa_reference_number, visa_expiration_date, student_id, updated_at, created_at) значения (201, ABCHFV4, 2019-12-31 00:00:00, 2019-01-11 08:03:06, 2019-01-11 08:03:06))

Ответы [ 2 ]

0 голосов
/ 16 июня 2019

Вы получаете ошибку, потому что студент еще не записан в базу данных de, поэтому новый экземпляр студента не назначен ни одному идентификатору. Если вы используете коллекции, данные немедленно записываются в базу данных. В функции модели вы можете использовать

$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]]);

Это запишет студента в базу данных и сгенерирует необходимый идентификатор. Я не уверен, как это влияет на производительность.

0 голосов
/ 12 января 2019

Ответ (и не спрашивайте меня почему, потому что на этом этапе документация так бедна) - использовать коллекции.

use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\ToCollection;

и вместо ToModel:

public function collection(Collection $rows)

и он ничего не «возвращает». Кроме этих изменений, использование точно такого же кода в OP работает как задумано.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...