laravel-admin 实现导入功能笔记

版本

  • php 7.2
  • ubuntu 18
  • laravel 6.18
  • laravel-admin 1.8
  • maatwebsite/excel 3.1

步骤

  • 添加导入数据按钮
  • 引入 maatwebsite/excel 包处理数据

添加导入数据按钮

运行下面的命令创建一个普通操作类:

php artisan admin:action Tenant\\ImportTenant --name="导入数据"

生成的类文件 app/Admin/Actions/Tenant/ImportTenant.php

<?php

namespace App\Admin\Actions\Tenant;

use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;

class ImportTenant extends Action
{
    protected $selector = '.import-tenant';

    public function handle(Request $request)
    {
        // $request ...

        return $this->response()->success('Success message...')->refresh();
    }

    public function html()
    {
        return <<<HTML
        <a class="btn btn-sm btn-default import-tenant">导入数据</a>
HTML;
    }
}

修改这个类,提供上传文件的功能,并加上处理数据的逻辑:

<?php

namespace App\Admin\Actions\Tenant;

use Encore\Admin\Actions\Action;
use Illuminate\Http\Request;

class ImportTenant extends Action
{
    protected $selector = '.import-tenant';

    public function handle(Request $request)
    {
        // 下面的代码获取到上传的文件,然后使用`maatwebsite/excel`等包来处理上传你的文件,保存到数据库
        $request->file('file');

        return $this->response()->success('导入完成!')->refresh();
    }

    public function form()
    {
        $this->file('file', '请选择文件');
    }

    public function html()
    {
        return <<<HTML
        <a class="btn btn-sm btn-default import-tenant"><i class="fa fa-upload"></i>导入数据</a>
HTML;
    }
}

修改app/Admin/Controller/TenantController.php, 将导入操作加入到表格的工具条中

class TenantController extends AdminController
{

    protected $title = '租客';


    protected function grid()
    {

        $grid = new Grid(new Tenant());

        .
        .
        .

        // 将导入操作加入到表格的工具条中
        $grid->tools(function (Grid\Tools $tools) {
            $tools->append(new ImportTenant());
        });


    }    

到这里完成添加导入按钮。

3IGgd.png

引入 maatwebsite/excel 包处理数据

安装包

composer require maatwebsite/excel

创建一个导入类

php artisan make:import TenantsImport --model=Models\\Tenant

生成的类文件app\Imports\TenantImport.php:

<?php

namespace App\Imports;

use App\Models\Tenant;
use Maatwebsite\Excel\Concerns\ToModel;

class TenantsImport implements ToModel
{

    public function model(array $row)
    {
        return new Tenant([
            //
        ]);
    }
}

修改类文件,设置字段对应的列

use App\Models\Tenant;
use Maatwebsite\Excel\Concerns\ToModel;

class TenantsImport implements ToModel
{

    public function model(array $row)
    {
        return new Tenant([
            'name' => $row[0],
            'phone' => $row[1],
            'id_card' => $row[2]
        ]);
    }
}

为了不读取表头,通过实现WithStartRow接口来设置从第二行开始读取数据

namespace App\Imports;

·
·
use Maatwebsite\Excel\Concerns\WithStartRow;

class TenantsImport implements ToModel, WithStartRow
{
   ·
   ·
   ·
    // 从2行开始读取数据
    public function startRow(): int
    {
        return 2;
    }
}

设置数据验证规则

<?php

namespace App\Imports;

.
.
.
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithValidation;


class TenantsImport implements ToModel, WithStartRow, WithValidation
{
    use Importable;

    .
    .
    .

    // 验证
    public function rules(): array
    {
        return [
            '0' => 'required',
        ];
    }
}

自定义验证信息


namespace App\Imports;
.
.
.

class TenantsImport implements ToModel, WithStartRow, WithValidation
{

    .
    .
    .
    // 自定义验证信息
    public function customValidationMessages()
    {
         '0.required' => '姓名未填',
    }

}

app\Admin\Actions\Tenant\ImportTenant.php调用导入

namespace App\Admin\Actions\Tenant;

.
.
use App\Imports\TenantsImport;

class ImportTenant extends Action
{
    protected $selector = '.import-tenant';

    public function handle(Request $request)
    {
        // 下面的代码获取到上传的文件,然后使用`maatwebsite/excel`等包来处理上传你的文件,保存到数据库
        $request->file('file');
        $import = new TenantsImport();
        $import->import($request->file('file'));
        return $this->response()->success('导入完成!')->refresh();
    }

    .
    .
    .


}

跳过验证失败的行

app\Imports\TenantImport.php

namespace App\Imports;
.
.
.
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\SkipsFailures;

class TenantsImport implements ToModel, WithStartRow, WithValidation, SkipsOnFailure
{
    use Importable, SkipsFailures;
    .
    .
    .

}

收集验证失败的行信息并显示

app\Admin\Actions\Tenant\ImportTenant.php:

namespace App\Admin\Actions\Tenant;

.
.
use App\Imports\TenantsImport;

class ImportTenant extends Action
{
    protected $selector = '.import-tenant';

    public function handle(Request $request)
    {
        // 下面的代码获取到上传的文件,然后使用`maatwebsite/excel`等包来处理上传你的文件,保存到数据库
        $import = new TenantsImport();
        $import->import($request->file('file'));
        $str = "";
        foreach ($import->failures() as $failure) {
            $str .=  ' 第'. $failure->row() . '行 失败原因:' . implode(' ', $failure->errors()) . '<br> 行数据:' . implode(' ', $failure->values()). '<br>';
        }
        if ($str !== '') {
            return $this->response()->error($str)->topFullWidth()->timeout(7000000);
        }
        return $this->response()->success('导入完成!')->refresh();
    }

    .
    .
    .


}

参考

laravel-admin 文档 模型表格-自定义行&批量操作

Laravel Excel 文档

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

怎么验证导入的数据是否唯一

2年前 评论
18369626100

那批量导入怎样实现

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!