当我使用Maatwebsite \ Excel软件包以及ToCollection时,如何正确验证Excel文件的内容?

时间:2019-06-10 08:13:01

标签: php excel laravel maatwebsite-excel

我正在尝试使用Maatwebsite \ Excel软件包将新用户导入系统。默认软件包问题ToModel不适合我,因为我需要为每个导入的用户分配默认角色,并为他/她发送电子邮件。我正在尝试使用ToCollection关注,如本文档页面最后一章所述:https://docs.laravel-excel.com/3.1/imports/validation.html。问题是我无法正确验证Excel文件的内容:根本没有出现错误消息。当我使用Maatwebsite \ Excel程序包并且与ToCollection有关时,如何正确验证Excel文件的内容?

也许您知道不同的方法来设置用户角色并在导入每个用户后发送电子邮件吗?

<?php

/* My controller and action which calls import of users: */


/* used namespaces go here */

class ProfileController extends Controller
{
    public function updateClient(UserClientRequest $request)
    {
        /* Client entity is being updated here, instead of this comment */

        // here I try to import users from *.xls file:
        $errors = [];
        if ($request->hasFile('file_to_import_users')) {
            $usersImport = new UsersImport($client->id);
            $usersImport->import($request->file('file_to_import_users'));
            foreach ($usersImport->failures() as $failure) {
                foreach ($failure->errors() as $error) {
                    $errors[] = $error;
                }
            }
        }

        return redirect()->route('profile.view_client')
            ->with('message', trans('client.updated'))
            ->with('validation_errors', $errors);
    }
}

/* My current UsersImport class: */

namespace App\Imports;

use App\User;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\ToCollection;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UsersImport implements WithValidation, SkipsOnFailure, ToCollection
{
    use Importable, SkipsFailures;

    private $clientId;

    public function __construct($clientId)
    {
        $this->clientId = $clientId;
    }


    public function collection(Collection $rows)
    {
        /* this does not work properly: */
        Validator::make($rows->toArray(), $this->rules())->validate();


        /* maybe I need to do something like this: */
        if ($validator->fails()) {
            return redirect()->route('profile.view_client')->with('validation_errors', $validator);
        }

        foreach ($rows as $row) {
            $user = new User();
            $user->first_name = $row[0];
            $user->last_name = $row[1];
            $user->email = $row[2];
            $user->password = Hash::make(Str::random(16));
            $user->client_id = $this->clientId;
            $user->save();

            DB::table('model_has_roles')->insert([
                'role_id' => 4,
                'model_type' => 'App\User',
                'model_id' => $user->id
            ]);
        }
    }

    public function rules(): array
    {
        return [
            '*.0' => 'required|max:255',
            '*.1' => 'required|max:255',
            '*.2' => 'required|unique:users,email|email|max:255',
        ];
    }

}

编辑:此问题被标记为“可能重复”,但我对此表示怀疑。我试图在UsersImport类的收集方法中编写此类代码:

    $validator = Validator::make($rows->toArray(), $this->rules());

    if ($validator->fails()) {
        return redirect()->route('profile.view_client')
            ->with('validation_errors', $validator->errors());
    }

它根本不起作用。我想我知道如何在Laravel中编写验证器,而且我希望我在某个地方犯了一个非常简单的错误。

1 个答案:

答案 0 :(得分:1)

最后,我自己解决了这个问题:

<?php

class ProfileController extends Controller
{

    public function updateClient(UserClientRequest $request)
    {
        if (!Auth::user()->hasRole('super-admin') && !Auth::user()->hasRole('admin')) {
            return redirect()->route('profile');
        }

        $client = Auth::user()->client;
        $client->name = $request->name;
        $client->type = $request->type;
        $client->save();

        $errors = [];

        if ($request->hasFile('file_to_import_companies')) {
            $companiesImport = new CompaniesImport($client->id);
            $companiesImport->import($request->file('file_to_import_companies'));
            foreach ($companiesImport->failures() as $failure) {
                foreach ($failure->errors() as $error) {
                    $errors[] = $error;
                }
            }
        }

        // this was changed:
        if ($request->hasFile('file_to_import_users')) {
            $usersImport = new UsersImport($client->id);
            $usersImport->import($request->file('file_to_import_users'));

            // I made function getErrors on UsersImport class:
            $usersValidationErrors = $usersImport->getErrors();
        } else {
            $usersValidationErrors = [];
        }

        $errors = array_merge($errors, $usersValidationErrors);

        return redirect()->route('profile.view_client')
            ->with('message', trans('client.updated'))
            ->with('validation_errors', $errors);
    }
}


/* Here is my UsersImport class: */

namespace App\Imports;

use App\User;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\Importable;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\SkipsFailures;
use Maatwebsite\Excel\Concerns\SkipsOnFailure;
use Maatwebsite\Excel\Concerns\ToCollection;
use Maatwebsite\Excel\Validators\Failure;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class UsersImport implements WithValidation, SkipsOnFailure, ToCollection
{
    use Importable, SkipsFailures;

    private $clientId;
    private $errors = []; // array to accumulate errors

    public function __construct($clientId)
    {
        $this->clientId = $clientId;
    }

    public function collection(Collection $rows)
    {
        $rows = $rows->toArray();

        // iterating each row and validating it:
        foreach ($rows as $key=>$row) {
            $validator = Validator::make($row, $this->rules(), $this->validationMessages());
            if ($validator->fails()) {
                foreach ($validator->errors()->messages() as $messages) {
                    foreach ($messages as $error) {
                        // accumulating errors:
                        $this->errors[] = $error;
                    }
                }
            } else {
                $user = new User();
                $user->first_name = $row[0];
                $user->last_name = $row[1];
                $user->email = $row[2];
                $user->password = Hash::make(Str::random(16));
                $user->client_id = $this->clientId;
                $user->locale = 'no';
                $user->save();

                DB::table('model_has_roles')->insert([
                    'role_id' => 4,
                    'model_type' => 'App\User',
                    'model_id' => $user->id
                ]);
            }
        }
    }

    // this function returns all validation errors after import:
    public function getErrors()
    {
        return $this->errors;
    }

    public function rules(): array
    {
        return [
            '0' => 'required|max:255',
            '1' => 'required|max:255',
            '2' => 'required|unique:users,email|email|max:255',
        ];
    }

    public function validationMessages()
    {
        return [
            '0.required' => trans('user.first_name_is_required'),
            '1.required' => trans('user.last_name_is_required'),
            '2.required' => trans('user.email_is_required'),
            '2.unique' => trans('user.email_must_be_unique'),
            '2.email' => trans('user.email_must_be_valid'),
        ];
    }

}