如何在maatwebsite-excel 3.1中跳过空行以在Laravel上进行模型方式导入

xcitsw88  于 2022-12-14  发布在  其他
关注(0)|答案(6)|浏览(405)

我正在用maatwebsite-exvel 3.1在laravel项目上工作,从文件上传方法导入excel文件。这是我的StudentsImport类。

public function model(array $row)
{
    return new Student([
        'school_uuid' => Auth::user()->school_uuid,
        'cardid'     => $row[0],
        'prefix'    => $row[1], 
        'name'    => $row[2], 
        'lastname'    => $row[3], 
        'dob'    => $row[4], 
        'address'    => $row[5], 
        'phone'    => $row[6], 
    ]);
}

下面是控制器。

Excel::import(new StudentsImport,  $request->file('file'));

代码工作正常。我可以导入excel的数据到数据库,但空行也导入。我想过滤/验证,以跳过这些空白之前,把数据库。任何建议或指导,这将是非常感谢,谢谢

unftdfkk

unftdfkk1#

根据package documentation,支持使用Laravel的验证来防止插入无效行。
要使用它,请在导入程序类上实现WithValidation接口,并添加一个rules()方法,该方法返回用于确保行有效的验证规则。

public function rules(): array
{
    return [
        '0' => 'required|string',
        '1' => 'required|string',
        '2' => 'required|numeric',
        // so on
    ];
}
qyyhg6bp

qyyhg6bp2#

请注意,rules()方法不会跳过空行,但会抛出一个错误,导致导入失败,并且验证的行将被回滚。
但是我发现这个特性存在于文档中,你只需在你的导入类中实现这个特性:“Maatwebsite\Excel\问题\失败时跳过”
像这样举个例子:

class UsersImport implements ToModel, WithValidation, SkipsOnFailure {
    // Your import class
}

然后在导入类中定义一个方法来处理错误:

/**
 * @param Failure[] $failures
 */
public function onFailure(Failure ...$failures)
{
    // Handle the failures how you'd like.
}

现在rules()方法不会再在空行上抛出错误,您可以静默地处理错误,您仍然应该使用rules()方法,因为您需要它来抛出现在可以由您处理的错误,也许您可以将它们记录到文件中,或者以您通常的方式进行操作。
最后,您将能够收集所有错误,以下是文档中的一个示例:

$import = new UsersImport();
$import->import('users.xlsx');

dd($import->errors());

因此,现在您可以静默地捕获错误,并最终将其返回给您的请求,您甚至可以返回如下详细信息:

foreach ($import->failures() as $failure) {
   $failure->row(); // row that went wrong
   $failure->attribute(); // either heading key (if using heading row concern) or column index
   $failure->errors(); // Actual error messages from Laravel validator
   $failure->values(); // The values of the row that has failed.
}

这不是复制粘贴材料好,我只是解释了你如何可以访问错误的基础上,在文件中给出的例子,我把它留给你来处理这些数据。
这里是一个链接到我发现所有这些信息的文档:https://docs.laravel-excel.com/3.1/imports/validation.html#skipping-failures

dw1jzc5e

dw1jzc5e3#

我使用了一种变通方法,这对我的情况很有帮助。验证通过对所有行使用nullable来扩展,以避免错误,然后在方法中,我添加了以下代码,它工作了

public function model(array $row) 
{
  if(!array_filter($row)) {
     return null;
  } 

  // your code will be here
   return new Student([
        'school_uuid' => Auth::user()->school_uuid,
        'cardid'     => $row[0],
        'prefix'    => $row[1], 
        'name'    => $row[2], 
        'lastname'    => $row[3], 
        'dob'    => $row[4], 
        'address'    => $row[5], 
        'phone'    => $row[6], 
    ]);

并在这一点上跳过这些行。我对此并不满意,因为我无法返回有用的错误消息,但我没有找到让代码运行的最佳方法。我在这里找到了这个。https://github.com/SpartnerNL/Laravel-Excel/issues/1861#issuecomment-520753182

ca1c2owp

ca1c2owp4#

尝试使用ToCollection,然后尝试是否满足($row-〉filter()-〉isNotEmpty())

public function collection(Collection $rows)
   {
      foreach($rows as $row) {
        if($row->filter()->isNotEmpty()){
            // you logic can go here
           }
        }   
   }

别忘了包括use Maatwebsite\Excel\Concerns\ToCollection;它对我很有效
参考可在此处找到。

aydmsdu9

aydmsdu95#

您也可以根据您所做的验证跳过行。如果您的请求之一没有被覆盖,您可以在模型中放置一个返回null

public function model(array $row)
{
    if ($row[2] === null || $row[3] === null ...) {
      return null;
    }
    return new Student([
        'school_uuid' => Auth::user()->school_uuid,
        'cardid'     => $row[0],
        'prefix'    => $row[1], 
        'name'    => $row[2], 
        'lastname'    => $row[3], 
        'dob'    => $row[4], 
        'address'    => $row[5], 
        'phone'    => $row[6], 
    ]);
}

此外,您还可以在必填字段的规则中添加验证规则“required_with”,如果在其他字段中存在将丢弃验证的内容,如果不存在,则跳过模型区域中返回空值的行。

public function rules(): array
{
    return [
        '0' => 'required_with:*.1,*.2,...', // here to be the others rows if they are populate to trow an validation error, 
        '1' => 'string|nullable|required_with:*.1,*.2,...',',
        // so on
    ];
}
yqyhoc1h

yqyhoc1h6#

您必须创建一个集合,并将其与筛选器而不是数组一起使用。首先将值修剪为非空的空格。然后在筛选空行后将其作为集合。

public function collection(Collection $rows)
    {
    foreach($rows as $row) {
        $em1=trim($row[0]);           

        $em = collect([$em1]);
       

        if($em->filter()->isNotEmpty()){
            // you logic can go here

            $user = Content::create([
                'email'     => $row[0],
                'phone'    => $row[1],
                'first_name'    => $row[2],
                'last_name'    => $row[3],
                'zip_code'    => $row[4],
                'address'    => $row[5],
            ]);
        }
    }
}

相关问题