Eloquente massale update van het model

Corrigeer me als ik het mis heb, maar ik denk dat er niet zoiets bestaat als een massale update in een welsprekend model.

Is er een manier om een ​​massale update van de DB-tabel uit te voeren zonder voor elke rij een query uit te voeren?

Bestaat er bijvoorbeeld een statische methode, zoiets als

User::updateWhere(
    array('age', '<', '18'),
    array(
        'under_18' => 1 
        [, ...]
    )
);

(ja, het is een dwaas voorbeeld, maar je snapt het wel…)

Waarom is zo’n functie niet geïmplementeerd?
Ben ik de enige die heel blij zou zijn als zoiets zich voordoet?

Ik (de ontwikkelaars), zou het niet willen implementeren zoals:

DB::table('users')->where('age', '<', '18')->update(array('under_18' => 1));

omdat naarmate het project groeit, we van de programmeurs kunnen verlangen dat ze in de toekomst de tabelnaam wijzigen en ze niet kunnen zoeken en vervangen voor de tabelnaam!

Is er zo’n statische methode om deze bewerking uit te voeren? En als dat niet het geval is, kunnen we dan de klasse Illuminate\Database\Eloquent\Modeluitbreiden om zoiets te bereiken?


Antwoord 1, autoriteit 100%

Misschien was dit een paar jaar geleden niet mogelijk, maar in recente versies van Laravel kun je dit zeker doen:

User::where('age', '<', 18)->update(['under_18' => 1]);

Het is vermeldenswaard dat je de waar-methode nodig hebt voordat je updateaanroept.


Antwoord 2, autoriteit 67%

Voor massa-update/insert-functies is gevraagd, maar Taylor Otwell (auteur van Laravel) stelt voor dat gebruikers in plaats daarvan Query Builder gebruiken. https://github.com/laravel/framework/issues/1295

Uw modellen zouden in het algemeen Illuminate\Database\Eloquent\Model moeten uitbreiden. Dan krijg je toegang tot de entiteit zelf, bijvoorbeeld als je dit hebt:

<?php
Use Illuminate\Database\Eloquent\Model;
class User extends Model {
    // table name defaults to "users" anyway, so this definition is only for
    // demonstration on how you can set a custom one
    protected $table = 'users';
    // ... code omited ...

Update #2

U moet uw toevlucht nemen tot de querybuilder. Om het probleem met de naamgeving van tabellen op te lossen, kunt u deze dynamisch verkrijgen via de methode getTable(). De enige beperking hiervan is dat u uw gebruikersklasse moet hebben geïnitialiseerd voordat u deze functie kunt gebruiken. Uw vraag zou als volgt zijn:

$userTable = (new User())->getTable();
DB::table($userTable)->where('age', '<', 18)->update(array('under_18' => 1));

Op deze manier is uw tabelnaam controller in het gebruikersmodel (zoals weergegeven in het bovenstaande voorbeeld).

Update #1

Een andere manier om dit te doen (niet efficiënt in uw situatie) zou zijn:

$users = User::where('age', '<', 18)->get();
foreach ($users as $user) {
    $user->field = value;
    $user->save();
}

Op deze manier blijft de tabelnaam in de gebruikersklasse en hoeven uw ontwikkelaars zich er geen zorgen over te maken.


Antwoord 3, autoriteit 16%

Een kleine correctie op het antwoord van @metamaker:

DB::beginTransaction();
     // do all your updates here
        foreach ($users as $user) {
            $new_value = rand(1,10) // use your own criteria
            DB::table('users')
               ->where('id', '=', $user->id)
               ->update(['status' => $new_value  // update your field(s) here
                ]);
        }
    // when done commit
DB::commit();

U kunt nu 1 miljoen verschillende updates hebben in één DB-transactie

Other episodes