Laravel insert or update multiple rows

别来无恙 提交于 2020-05-25 04:44:05

问题


Im new in laravel, and im trying to update my navigation tree. So i want to update my whole tree in one query without foreach.

array(
  array('id'=>1, 'name'=>'some navigation point', 'parent'='0'),
  array('id'=>2, 'name'=>'some navigation point', 'parent'='1'),
  array('id'=>3, 'name'=>'some navigation point', 'parent'='1')
);

I just want to ask - is there posibility in laravel to insert(if new in array) or update my current rows in database?

I want to update all, because i have fields _lft, _right, parent_id in my tree and im using some dragable js plugin to set my navigation structure - and now i want to save it.

I tried to use

Navigation::updateOrCreate(array(array('id' => '3'), array('id'=>'4')), array(array('name' => 'test11'), array('name' => 'test22')));

But it works just for single row, not multiple like i tried to do. Maybe there is another way to do it?


回答1:


I wonder why this kind of feature is not yet available in Laravel core (till today). Check out this gist The result of the query string would look like this: here

I am putting the code here just in case the link breaks in the future, I am not the author:

/**
* Mass (bulk) insert or update on duplicate for Laravel 4/5
* 
* insertOrUpdate([
*   ['id'=>1,'value'=>10],
*   ['id'=>2,'value'=>60]
* ]);
* 
*
* @param array $rows
*/
function insertOrUpdate(array $rows){
    $table = \DB::getTablePrefix().with(new self)->getTable();


    $first = reset($rows);

    $columns = implode( ',',
        array_map( function( $value ) { return "$value"; } , array_keys($first) )
    );

    $values = implode( ',', array_map( function( $row ) {
            return '('.implode( ',',
                array_map( function( $value ) { return '"'.str_replace('"', '""', $value).'"'; } , $row )
            ).')';
        } , $rows )
    );

    $updates = implode( ',',
        array_map( function( $value ) { return "$value = VALUES($value)"; } , array_keys($first) )
    );

    $sql = "INSERT INTO {$table}({$columns}) VALUES {$values} ON DUPLICATE KEY UPDATE {$updates}";

    return \DB::statement( $sql );
}

So you can safely have your arrays inserted or updated as:

insertOrUpdate(
    array(
      array('id'=>1, 'name'=>'some navigation point', 'parent'='0'),
      array('id'=>2, 'name'=>'some navigation point', 'parent'='1'),
      array('id'=>3, 'name'=>'some navigation point', 'parent'='1')
    )
);

Just in case any trouble with the first line in the function you can simply add a table name as a second argument, then comment out the line i.e:

function insertOrUpdate(array $rows, $table){
    .....
}

insertOrUpdate(myarrays,'MyTableName');

NB: Be careful though to sanitise your input! and remember the timestamp fields are not touched. you can do that by adding manually to each arrays in the main array.




回答2:


Eloquent Style

public function meta(){ // in parent models.
    return $this->hasMany('App\Models\DB_CHILD', 'fk_id','local_fk_id');
}

. . .

$parent= PARENT_DB::findOrFail($id);
$metaData= [];
        foreach ($meta['meta'] as $metaKey => $metaValue) {

            if ($parent->meta()->where([['meta_key', '=',$metaKey]] )->exists()) { 
                $parent->meta()->where([['meta_key', '=',$metaKey]])->update(['meta_value' => $metaValue]);
            }else{
                $metaData[] = [
                    'FK_ID'=>$fkId,
                    'meta_key'=>$metaKey,
                    'meta_value'=> $metaValue
                ];
            }

        }
$Member->meta()->insert($metaData);



回答3:


No, you can't do this. You can insert() multiple rows at once and you can update() multiple rows using same where() condition, but if you want to use updateOrCreate(), you'll need to use foreach() loop.




回答4:


in your controller use DB; public function arrDta(){

        $up_or_create_data=array(
            array('id'=>2, 'name'=>'test11'),
            array('id'=>4, 'name'=>'test22')

        );

        var_dump($up_or_create_data);
        echo "fjsdhg";

        foreach ($up_or_create_data as $key => $value) {
            echo "key  ".$key;
            echo "<br>";
            echo " id: ".$up_or_create_data[$key]["id"];
            echo "<br>";
            echo " Name: ".$up_or_create_data[$key]["name"];


        if (Navigation::where('id', '=',$up_or_create_data[$key]["id"])->exists()) {
            DB::table('your_table_ name')->where('id',$up_or_create_data[$key]["id"])->update(['name' => $up_or_create_data[$key]["name"]]);
        }else{
            DB::insert('insert into your_table_name (id, name) values (?, ?)', [$up_or_create_data[$key]["id"], $up_or_create_data[$key]["name"]]);
        }

        }



回答5:


I've created an UPSERT package for all databases: https://github.com/staudenmeir/laravel-upsert

DB::table('navigation')->upsert(
    [
        ['id' => 1, 'name' => 'some navigation point', 'parent' => '0'],
        ['id' => 2, 'name' => 'some navigation point', 'parent' => '1'],
        ['id' => 3, 'name' => 'some navigation point', 'parent' => '1'],
    ],
    'id'
);


来源:https://stackoverflow.com/questions/40863015/laravel-insert-or-update-multiple-rows

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!