【问题标题】:How To Mass Attach Relationship Of Arrays Data From Imported Excel? Laravel, php如何从导入的 Excel 中批量附加数组数据的关系?拉拉维尔,PHP
【发布时间】:2021-11-06 14:23:14
【问题描述】:

我终于可以将excel数据导入数据库(虽然与通常导入的代码不同),但它无法附加关系。

三个表:users(第一个表)、role_user(关系表)和roles(第二个表)

错误:在布尔值上调用成员函数角色() Screenshot of the error

UserImport.php

use App\User;
use Maatwebsite\Excel\Concerns\ToModel;

class UserImport implements ToModel
{
    /**
    * @param array $row
    *
    * @return \Illuminate\Database\Eloquent\Model|null
    */
    public function model(array $row)
    {
        return new User([
        'nisn' => $row[1],
        'name' => $row[2],
        'username' => $row[3],
        'email' => $row[4],
        'kelas' => $row[5],
        'jabatan' => $row[6],
        'tempat_lahir' => $row[7],
        'tgl_lahir' => $row[8],
        'bulan_lahir' => $row[9],
        'tahun_lahir' => $row[10],
        'jenis_kelamin' => $row[11],
        'agama' => $row[12],
        'tahun_masuk' => $row[13],
        'no_telp' => $row[14],
        'password' => $row[15],
        ]);
    }
}

AdminController.php(部分)

public function import_student(Request $request) 
    {
    $this->validate($request, [
        'file' => 'required|mimes:csv,xls,xlsx'
    ]);
    $import = Excel::toArray(new UserImport(), $request->file('file'));
        foreach($import[0] as $row) {
            //  dd($row[1].' '.$row[2]);
            $arr[] = [
                // If uncomment this id from here, remove [0] from foreach
                // 'id' => $row[0], 
                'nisn' => $row[1],
                'name' => $row[2],
                'username' => $row[3],
                'email' => $row[4],
                'kelas' => $row[5],
                'jabatan' => $row[6],
                'tempat_lahir' => $row[7],
                'tgl_lahir' => $row[8],
                'bulan_lahir' => $row[9],
                'tahun_lahir' => $row[10],
                'jenis_kelamin' => $row[11],
                'agama' => $row[12],
                'tahun_masuk' => $row[13],
                'no_telp' => $row[14],
                'password' => Hash::make($row[15]),
            ];
        }
        if(!empty($arr)){
            User::insert($arr)->roles()->attach(Role::where('name', 'Student'));
        }    
    if($import) {
        //redirect
        return redirect()->back()->with(['success' => 'Data Berhasil Diimport!']);
    } else {
        //redirect
        return redirect()->back()->with(['error' => 'Data Gagal Diimport!']);
    }
    }

我检查了数据库,果然,从 excel 导入数据是成功的......只是这段代码 ->roles()->attach(Role::where('name', 'Student')); 似乎只在它不是多个数组数据时才有效(只在创建中工作,而不是插入)。

有没有办法为所有插入的数组数据批量附加关系?

【问题讨论】:

    标签: php arrays laravel import relationship


    【解决方案1】:

    有没有办法为所有插入的数组数据批量附加关系?

    很遗憾,没有。您必须实现自定义逻辑才能将角色附加到您插入的用户。例如,您可以为当前正在导入的用户添加一个布尔列 is_importing

    首先将is_importing 列添加到您的用户表中,然后:

    public function import_student(Request $request) 
        {
        $this->validate($request, [
            'file' => 'required|mimes:csv,xls,xlsx'
        ]);
        $import = Excel::toArray(new UserImport(), $request->file('file'));
            foreach($import[0] as $row) {
                //  dd($row[1].' '.$row[2]);
                $arr[] = [
                    // If uncomment this id from here, remove [0] from foreach
                    // 'id' => $row[0], 
                    'nisn' => $row[1],
                    'name' => $row[2],
                    'username' => $row[3],
                    'email' => $row[4],
                    'kelas' => $row[5],
                    'jabatan' => $row[6],
                    'tempat_lahir' => $row[7],
                    'tgl_lahir' => $row[8],
                    'bulan_lahir' => $row[9],
                    'tahun_lahir' => $row[10],
                    'jenis_kelamin' => $row[11],
                    'agama' => $row[12],
                    'tahun_masuk' => $row[13],
                    'no_telp' => $row[14],
                    'password' => Hash::make($row[15]),
                    'is_importing' => true // here we set importing to true, so our "not fully imported students" are marked
                ];
            }
            if(!empty($arr)){
                User::query()->insert($arr); //good, just be careful of the size limit of $arr, you may need to chunk it
    
                $role = Role::query()->where('name', 'Student')->first();
    
                $role->users()->syncWithoutDetaching(
                   User::query()->where('is_importing', true)->pluck('id')
                ); 
                // we add all of users to the $role
                // don't forget to define the users relationship in your Role model
    
                User::query()->update(['is_importing' => false]);
                // we conclude our import by setting is_importing to false
            }    
        if($import) {
            //redirect
            return redirect()->back()->with(['success' => 'Data Berhasil Diimport!']);
        } else {
            //redirect
            return redirect()->back()->with(['error' => 'Data Gagal Diimport!']);
        }
    }
    

    为什么你不能User::insert($arr)->roles()->attach(Role::where('name', 'Student'));

    User::insert()User::query()->insert() 的快捷方式,可让您批量插入数据。它很有用,因为它速度很快,但就像 User::query()->update() 一样,它只允许您执行插入查询以外的任何操作。

    另外说,打电话……

    User::query()->insert([
       'col1' => 'val1',
       'col2' => 'val2',
    ]);
    

    ...就像调用:

    DB::statement('INSERT INTO users (col1, col2) VALUES (val1, val2)');
    

    它会根据查询状态返回一个布尔值(如果它插入了东西),但没有别的。

    因此:

    User::insert($arr)->roles()->attach(Role::where('name', 'Student')); // Call to a member function roles() on boolean
    
    // because insert() returns a boolean it's like writing
    
    true->roles()->attach(Role::where('name', 'Student')); // Call to a member function roles() on boolean
    

    在当前问题之后,您将在代码中遇到的另一个问题是 ->roles()->attach(Role::where('name', 'Student')) 将不起作用,因为 attach() 需要模型实例、id 或 id 数组。在这里,您提供了一个查询生成器 (Role::where('name', 'Student')),您需要附加 ->first()

    【讨论】:

    • 我制作的时候能问一下'is_importing'一栏是什么类型的数据吗?我知道它是布尔值,因为 true 和 false 声明,但只是为了确定它是否需要是字符串数据或其他数据。
    • 在您的数据库中,布尔值应该是tinyint(1),在这种情况下默认值为0。如果您通过迁移(Laravel 方式)添加它,则为 $table->boolean('is_importing')
    • 请记住,这只是进行此导入的一种方式,还有很多其他方式,有些最差,有些更好,最后只有您可以选择什么是“正确”的方式,因为您知道你的要求比这里的任何人都好:)
    • 我看到您是 stackoverflow 的新手,如果它解决了您的问题,请不要忘记验证答案(此处和您的其他问题)。这样,任何有类似问题的人都可以轻松解决:)
    • 拥有此帐户 9 个月,但对这一切仍然陌生。好吧,当我执行通常的 User::import 时它失败了...但在 toArray 中成功...我会在尝试后验证您的答案,还有另一件事要做。
    猜你喜欢
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 2019-12-22
    • 2021-06-14
    • 2015-10-04
    • 2021-08-15
    • 2017-03-12
    • 1970-01-01
    相关资源
    最近更新 更多