Laravel Excel的`prepareForValidation`方法在每行调用两次。

huangapple go评论60阅读模式
英文:

Laravel Excel `prepareForValidation` method being called twice per row

问题

我目前正在使用Laravel Excel包开发Excel导入功能。我正在实现OnEachRowWithHeadingRowWithValidationSkipsEmptyRowsSkipsOnFailureSkipsOnErrorWithEvents接口。

我的类使用prepareForValidation方法在数据被验证之前准备和操作数据。然而,似乎在导入过程中,prepareForValidation方法对每一行都被调用了两次。这导致了意外的结果。

以下是我在prepareForValidation方法中使用的代码段:

public function prepareForValidation($data, $index)
{
    dump($index, $data); // 调试
    $rules = $this->rules();

    foreach ($data as $key => $value) {
        if (empty($rules[$key]))
            continue;

        if (in_array('date', $rules[$key])) {
            $data[$key] = Date::excelToDateTimeObject($value);
        }

        if (in_array('boolean', $rules[$key])) {
            $data[$key] = human2Bool($value);
        }
    }

    unset($data['']);

    dump($data); //调试

    return $data;
}

如你所见,在prepareForValidation方法中,我将Excel日期转换为DateTime对象,将一些布尔值从人类可读格式转换为布尔格式。然而,奇怪的是,如果我删除Date::excelToDateTimeObject的转换,这种行为就不会发生...

第一次prepareForValidation调用:

"行索引:" 3
"函数开始时的数据:"
array:8 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "" => 1
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => "n"
  "end_at" => 45056
  "duration" => null
  "methodological_status" => null
]
"函数结束时的数据:"
array:7 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => false
  "end_at" => "2023-05-10"
  "duration" => null
  "methodological_status" => null
]

第二次prepareForValidation调用:

"行索引:" 3
"函数开始时的数据:"
array:8 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "" => "1"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => "n"
  "end_at" => "45056"
  "duration" => null
  "methodological_status" => null
]
"函数结束时的数据:"
array:7 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => false
  "end_at" => "2023-05-10"
  "duration" => null
  "methodological_status" => null
]

如上所示,在第一次prepareForValidation调用期间,'end_at'字段是一个整数(Excel的数字日期格式)。转换后,它变成了一个DateTime对象("2023-05-10")。然而,在第二次prepareForValidation调用期间,'end_at'字段再次变成了字符串("45056")。

我尝试将'end_at'验证规则更改为date_format:Y-m-d,但问题仍然存在。

有人之前遇到过这个问题吗?有没有解释为什么prepareForValidation会对每一行调用两次的情况,以及如何防止这种情况发生?

我正在使用Laravel Excel版本3.1

非常感谢任何帮助。

英文:

I'm currently working on an Excel import feature using the Laravel Excel package. I'm implementing OnEachRow, WithHeadingRow, WithValidation, SkipsEmptyRows, SkipsOnFailure, SkipsOnError, and WithEvents interfaces.

My class uses prepareForValidation method to prepare and manipulate the data before it's validated. However, it seems that prepareForValidation is being called twice for each row during the import process. This is leading to unexpected results.

Here's an excerpt of my class where I'm using prepareForValidation:

public function prepareForValidation($data, $index)
{
    dump($index, $data); // debug
    $rules = $this->rules();

    foreach ($data as $key => $value) {
        if (empty($rules[$key]))
            continue;

        if (in_array('date', $rules[$key])) {
            $data[$key] = Date::excelToDateTimeObject($value);
        }

        if (in_array('boolean', $rules[$key])) {
            $data[$key] = human2Bool($value);
        }
    }

    unset($data['']);

    dump($data); //debug

    return $data;
}

As you can see, in the prepareForValidation method, I'm converting Excel dates into a DateTime object and some booleans from human readable format to boolean format. However, it seems that the function is called again with the same row data, after the initial data transformation. The strange thing is, that if I remove the Date::excelToDateTimeObject transformation, this behavior does not happen...

First prepareForValidation call:

"row index:" 3
"data at the beginning of the function:"
array:8 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "" => 1
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => "n"
  "end_at" => 45056
  "duration" => null
  "methodological_status" => null
]
"data at the end of the function:"
array:7 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => false
  "end_at" => "2023-05-10"
  "duration" => null
  "methodological_status" => null
]

Second prepareForValidation call:

"row index:" 3
"data at the beginning of the function:"
array:8 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "" => "1"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => "n"
  "end_at" => "45056"
  "duration" => null
  "methodological_status" => null
]
"data at the end of the function:"
array:7 [
  "name" => "Test one"
  "uuid" => "656e9c21-b77a-4a9a-ba3d-e2490effcadd"
  "execution_structure_id" => "fc1fbdf8-ea73-4d0a-a9a5-f1530a3d49b8"
  "is_locked" => false
  "end_at" => "2023-05-10"
  "duration" => null
  "methodological_status" => null
]

As seen above, during the first call of prepareForValidation, the 'end_at' field is an integer (Excel's numeric date format). After conversion, it turns into a DateTime object ("2023-05-10"). However, in the second call of prepareForValidation, the 'end_at' field has reverted to being a string again ("45056").

I tried changing the 'end_at' validation rule to date_format:Y-m-d but the issue persists.

Has anyone experienced this before? Is there any explanation for why prepareForValidation would be called twice per row and how can I prevent this from happening?

I'm using the Laravel Excel version 3.1.

Any help would be much appreciated.

答案1

得分: 0

在我的 public function onRow(Row $row) 中,我使用了 $row->toCollection()$row->toArray()。这些会重新触发验证过程,从而再次调用 prepareForValidation...

英文:

Okay, I got it! In my public function onRow(Row $row) I use $row->toCollection() and $row->toArray(). Those are retriggering the validation process and with that the prepareForValidation gets also called again...

huangapple
  • 本文由 发表于 2023年6月12日 22:11:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76457509.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定