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 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。