Démarrage rapide


Eloquent : Démarrage

Conventions de modèle éloquentes

Maintenant, regardons un exemple du modèle Flight, que nous utiliserons pour récupérer et stocker les informations de données de la table de base de données flights :

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{ 
       //
    }

Nom de la table de données

Veuillez noter que nous n'indiquons pas à Eloquent quelle table de données utiliser pour notre modèle Flight. Sauf si un autre nom est explicitement spécifié, le pluriel de la classe, « serpents », sera utilisé comme nom de table. Par conséquent, dans ce cas, Eloquent supposera que le modèle Flight stocke les données de la table de données flights. Vous pouvez spécifier une table de données personnalisée en définissant l'attribut table sur le modèle : Flight 模型使用哪个数据表。 除非明确地指定了其它名称,否则将使用类的复数形式「蛇形命名」来作为表名。因此,在这种情况下,Eloquent 将假设 Flight 模型存储的是 flights 数据表中的数据。你可以通过在模型上定义 table 属性来指定自定义数据表:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{ 
    /**
     * 与模型关联的表名
     *
     * @var string
     */  
   protected $table = 'my_flights';
 }

主键

Eloquent 也会假设每个数据表都有一个名为 id 的主键列。你可以定义一个受保护的 $primaryKey 属性来重写约定。

此外,Eloquent 假设主键是一个自增的整数值,这意味着默认情况下主键会自动转换为 int 类型。如果您希望使用非递增或非数字的主键则需要设置公共的  $incrementing 属性设置为 false。如果你的主键不是一个整数,你需要将模型上受保护的 $keyType 属性设置为 string

时间戳

默认情况下,Eloquent 预期你的数据表中存在 created_atupdated_at 。如果你不想让 Eloquent 自动管理这两个列, 请将模型中的 $timestamps 属性设置为 false

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{    
    /**
     * 指示模型是否自动维护时间戳
     *
     * @var bool
     */    
   public $timestamps = false;
  }

如果需要自定义时间戳的格式,在你的模型中设置 $dateFormat 属性。这个属性决定日期属性在数据库的存储方式,以及模型序列化为数组或者 JSON 的格式:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{   
     /**
     * 模型日期列的存储格式。
     *
     * @var string
     */   
     protected $dateFormat = 'U';
    }

如果你需要自定义存储时间戳的字段名,可以在模型中设置 CREATED_ATUPDATED_AT 常量的值来实现:

<?php
    class Flight extends Model{
        const CREATED_AT = 'creation_date';    
        const UPDATED_AT = 'last_update';
     }

数据库连接

默认情况下,Eloquent 模型将使用你的应用程序配置的默认数据库连接。如果你想为模型指定一个不同的连接,设置 $connection 属性:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{   
     /**
     * 模型的连接名称
     *
     * @var string
     */   
     protected $connection = 'connection-name';
   }

默认属性值

如果要为模型的某些属性定义默认值,可以在模型上定义 $attributes

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{  
      /**
     * 模型的默认属性值。
     *
     * @var array
     */  
      protected $attributes = [      
        'delayed' => false,   
         ];
      }

Clé primaireEloquent assumera également que chaque table de données a une colonne de clé primaire nommée id. Vous pouvez remplacer la convention en définissant un attribut $primaryKey protégé.

De plus, Eloquent suppose que la clé primaire est une valeur entière auto-incrémentée, ce qui signifie que la clé primaire est automatiquement convertie en type int par défaut. Si vous souhaitez utiliser une clé primaire non incrémentée ou non numérique, vous devez définir la propriété publique $incrementing sur false. Si votre clé primaire n'est pas un entier, vous devez définir la propriété protégée $keyType sur le modèle sur string.

Timestamp

Par défaut, Eloquent attend created_at et updated_at . Si vous ne souhaitez pas qu'Eloquent gère automatiquement ces deux colonnes, veuillez définir l'attribut $timestamps dans le modèle sur false :
<?php
    $flights = App\Flight::all();
    foreach ($flights as $flight) {   
     echo $flight->name;
    }
Si vous devez personnaliser le format d'horodatage , Définissez la propriété $dateFormat dans votre modèle. Cet attribut détermine comment l'attribut date est stocké dans la base de données et le format dans lequel le modèle est sérialisé dans un tableau ou JSON : 🎜
$flights = App\Flight::where('active', 1)         
      ->orderBy('name', 'desc')               
      ->take(10)               
      ->get();
🎜 Si vous devez personnaliser le nom du champ pour stocker les horodatages, vous pouvez définir CREATED_AT dans le modèle et la valeur de la constante UPDATED_AT : 🎜
$flight = App\Flight::where('number', 'FR 900')->first();
$freshFlight = $flight->fresh();
🎜🎜Connexion à la base de données🎜🎜Par défaut, l'Eloquent Le modèle sera utilisé par votre application Connexion à la base de données par défaut configurée. Si vous souhaitez spécifier une connexion différente pour le modèle, définissez l'attribut $connection : 🎜
$flight = App\Flight::where('number', 'FR 900')->first();
$flight->number = 'FR 456';$flight->refresh();
$flight->number;
 // "FR 900"
🎜🎜🎜
🎜

Valeurs d'attribut par défaut

🎜Si vous souhaitez définir des valeurs par défaut pour certains attributs du modèle, vous pouvez définir l'attribut $attributes sur le modèle : 🎜
$flights = $flights->reject(function ($flight) { 
   return $flight->cancelled;
 });
🎜🎜🎜 🎜🎜🎜🎜Récupération du modèle🎜🎜Après avoir créé le modèle et sa table de base de données associée, vous pouvez interroger les données de la base de données. Considérez chaque modèle Eloquent comme un puissant générateur de requêtes que vous pouvez utiliser pour interroger plus rapidement la table de données associée. Par exemple : 🎜
foreach ($flights as $flight) {
    echo $flight->name;
  }
🎜🎜

Contraintes supplémentaires

La méthode all d'Eloquent renverra tous les résultats du modèle. Puisque chaque modèle Eloquent agit comme un constructeur de requêtes, vous pouvez également ajouter des conditions de requête, puis utiliser la méthode get pour obtenir les résultats de la requête : all 方法会返回模型中所有的结果。由于每个 Eloquent 模型都充当一个查询构造器,所以你也可以添加查询条件,然后使用 get 方法获取查询结果:

Flight::chunk(200, function ($flights) { 
   foreach ($flights as $flight) {   
        //  
      }
  });

{tip} 因为 Eloquent 模型也是查询构造器,所以你也应当阅读 查询构造器可用的所有方法。你可以在 Eloquent 查询中使用这些方法。

重新加载模型

你可以使用 freshrefresh 方法重新加载模型。 fresh 方法会重新从数据库中检索模型。现有的模型实例不受影响:

foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
    //
 }

refresh 方法使用数据库中的新数据重新赋值现有模型。此外,已经加载的关系会被重新加载:

// 通过主键检索一个模型...
$flight = App\Flight::find(1);
// 检索符合查询限制的第一个模型...
$flight = App\Flight::where('active', 1)->first();

集合

对于 Eloquent 中的 allget 方法可以查询多个结果,返回一个 IlluminateDatabaseEloquentCollection 实例。  Collection 类提供了 很多辅助函数 来处理 Eloquent 结果:

$flights = App\Flight::find([1, 2, 3]);

你可以像数组一样遍历集合:

$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();

分块结果

如果你需要处理数以千计的 Eloquent 结果,使用 chunk 命令。 chunk 方法会检索 Eloquent 模型中的『分块』将他们提供给指定的 Closure 处理。在处理大型结果集时,使用  chunk 方法可以节省内存:

Route::get('/api/flights/{id}', function ($id) { 
   return App\Flight::findOrFail($id);
 });

传递到方法的第一个参数是希望每个『分块』接收的数据量。闭包作为第二个参数传递,它在每次从数据库中检索分块的时候调用。它将执行数据库查询把检索分块的结果传递给闭包方法。

使用游标

cursor 方法允许你使用游标遍历数据库,它只执行一次查询。处理大量的数据时, cursor 方法可以大大减少内存的使用量:

$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');

检索单个模型 / 集合

除了从指定的数据表检索所有记录外,你可以使用 findfirst 方法来检索单条记录。这些方法返回单个模型实例,而不是返回模型集合:

<?php
    namespace App\Http\Controllers;
    use App\Flight;use Illuminate\Http\Request;
    use App\Http\Controllers\Controller;
    class FlightController extends Controller{   
     /**
     * 创建一个新的航班实例
     *
     * @param  Request  $request
     * @return Response
     */  
     public function store(Request $request)   
      {      
        // 校验请求...        
        $flight = new Flight;        
        $flight->name = $request->name;        
        $flight->save();  
        }
   }

你也可以使用主键数组作为参数调用 find

$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';$flight->save();

{tip} Parce que les modèles Eloquent sont également des requêtes constructors constructeur, vous devriez donc également lire toutes les méthodes disponibles pour le générateur de requêtes. Vous pouvez utiliser ces méthodes dans les requêtes Eloquent.
🎜Recharger le modèle🎜🎜Vous pouvez recharger en utilisant les méthodes fresh et refresh Modèle. La méthode fresh récupère à nouveau le modèle de la base de données. Les instances de modèle existantes ne sont pas affectées : 🎜
App\Flight::where('active', 1)    
      ->where('destination', 'San Diego')          
      ->update(['delayed' => 1]);
🎜 La méthode refresh réaffecte un modèle existant avec de nouvelles données de la base de données. De plus, les relations déjà chargées seront rechargées : 🎜
<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{  
      /**
     * 可以被批量赋值的属性。
     *
     * @var array
     */   
     protected $fillable = ['name'];
  }
🎜🎜
🎜

Collections

🎜 Les méthodes all et get dans Eloquent peuvent interroger plusieurs résultats et renvoyer une instance IlluminateDatabaseEloquentCollection. La classe Collection fournit un certain nombre de fonctions d'assistance pour gérer les résultats Eloquent : 🎜
$flight = App\Flight::create(['name' => 'Flight 10']);
🎜Vous pouvez parcourir la collection comme un tableau : 🎜
$flight->fill(['name' => 'Flight 22']);
🎜🎜
🎜

Chunk results

🎜Si vous devez traiter des milliers de résultats Eloquent, utilisez la commande chunk. La méthode chunk récupère les "morceaux" dans le modèle Eloquent et les fournit au Closure spécifié pour traitement. Lors du traitement de grands ensembles de résultats, utilisez la méthode chunk pour économiser de la mémoire : 🎜
<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class Flight extends Model{    
    /**
     * 不可批量赋值的属性。
     *
     * @var array
     */   
   protected $guarded = ['price'];
 }
🎜Le premier paramètre transmis à la méthode est la quantité de données que vous souhaitez que chaque "chunk" reçoive. La fermeture est passée en deuxième paramètre et est appelée chaque fois qu'un morceau est récupéré de la base de données. Il exécutera la requête de base de données et transmettra les résultats fragmentés récupérés à la méthode de fermeture. 🎜
🎜🎜Utilisation des curseurs🎜🎜La méthode cursor permet de parcourir la base de données à l'aide d'un curseur, qui effectue uniquement une requête. Lors du traitement de grandes quantités de données, la méthode cursor peut réduire considérablement l'utilisation de la mémoire : 🎜
/**
 * 不可以批量赋值的属性。
 *
 * @var array
 */
 protected $guarded = [];
🎜🎜
🎜

Récupérer un seul modèle/collection

🎜En plus de récupérer tous les enregistrements d'une table de données spécifiée, vous pouvez utiliser find ou first< /code> méthode pour récupérer un seul enregistrement. Ces méthodes renvoient une seule instance de modèle au lieu d'une collection de modèles : 🎜
// 通过 name 来查找航班,不存在则创建...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// 通过 name 查找航班,不存在则使用 name 和 delayed 属性创建...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10'], ['delayed' => 1]);
//  通过 name 查找航班,不存在则创建一个实例...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
// 通过 name 查找航班,不存在则使用 name 和 delayed 属性创建一个实例...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10'], ['delayed' => 1]);
🎜 Vous pouvez également appeler la méthode find avec un tableau de clés primaires comme argument, qui renverra une collection d'enregistrements correspondants : 🎜
// 如果有从奥克兰到圣地亚哥的航班,则价格定为99美元。
// 如果没匹配到存在的模型,则创建一个。
$flight = App\Flight::updateOrCreate( 
   ['departure' => 'Oakland', 'destination' => 'San Diego'],    
   ['price' => 99]
 );
🎜🎜

『Not Found』Exception

Parfois, vous souhaitez lever une exception lorsqu'un modèle n'est pas trouvé. Ceci est très utile dans les contrôleurs et le routage. Les méthodes findOrFail et firstOrFail récupéreront le premier résultat de la requête. S'il n'est pas trouvé, IlluminateDatabaseEloquentModelNotFoundException sera levée : findOrFailfirstOrFail 方法会检索查询的第一个结果,如果未找到,将抛出 IlluminateDatabaseEloquentModelNotFoundException 异常:

$flight = App\Flight::find(1);
$flight->delete();

如果没有捕获异常,则会自动返回 404 响应给用户。也就是说,使用这些方法时,没有必要再写个检查来返回 404 响应::

App\Flight::destroy(1);
App\Flight::destroy(1, 2, 3);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(collect([1, 2, 3]));

检索集合

你还可以使用 查询构造器 提供的 countsummax, 和其他的聚合函数。这些方法只会返回适当的标量值而不是一个模型实例:

$deletedRows = App\Flight::where('active', 0)->delete();

插入 & 更新模型

插入

要往数据库新增一条记录,先创建新模型实例,给实例设置属性,然后调用 save 方法:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\SoftDeletes;
    class Flight extends Model{
        use SoftDeletes;
       }

在这个示例中,我们将 HTTP 请求参数 name 赋值给了 AppFlight 模型实例的 name 属性。当调用 save 方法时,将会插入一条新记录。 created_atupdated_at 时间戳将会自动设置,不需要手动赋值。

更新

save 方法也可以用来更新数据库已经存在的模型。更新模型,你需要先检索出来,设置要更新的属性,然后调用 save 方法。同样, updated_at 时间戳会自动更新,所以也不需要手动赋值:

Schema::table('flights', function (Blueprint $table) 
{  
  $table->softDeletes();
});

批量更新

也可以更新匹配查询条件的多个模型。在这个示例中,所有的 active 和  destinationSan Diego 的航班会标记为延误:

if ($flight->trashed()) {
    //
 }

update 方法接受一个键为字段名称数据为值的数组。

{note} 通过 Eloquent 批量更新时, 更新的模型不会触发 savedupdated

$flights = App\Flight::withTrashed()           
     ->where('account_id', 1)                
     ->get();

If. Si aucune exception n'est détectée, une réponse 404 sera automatiquement renvoyée à l'utilisateur. Autrement dit, lorsque vous utilisez ces méthodes, il n'est pas nécessaire d'écrire un chèque pour renvoyer une réponse 404 : 
$flight->history()->withTrashed()->get();

Récupérer une collection

Vous pouvez également utiliser le count, la sum, le max fournis par le générateur de requêtes et d'autres fonctions d'agrégation. Ces méthodes renverront simplement la valeur scalaire appropriée plutôt qu'une instance de modèle :
$flights = App\Flight::onlyTrashed()           
     ->where('airline_id', 1)                
     ->get();
🎜🎜🎜
🎜

Insérer et mettre à jour le modèle

🎜
🎜🎜
🎜

Insérer

🎜Aller à ajoutez un nouvel enregistrement à la base de données, créez d'abord une nouvelle instance de modèle, définissez les propriétés de l'instance, puis appelez la méthode save : 🎜
$flight->restore();
🎜Dans cet exemple, nous modifions le paramètre de requête HTTP name Attribué à l'attribut name de l'instance de modèle AppFlight. Lorsque la méthode save est appelée, un nouvel enregistrement sera inséré. Les horodatages created_at et updated_at seront définis automatiquement et ne nécessiteront pas d'affectation manuelle. 🎜🎜
🎜🎜
🎜

update

🎜save peut également être utilisée Mettez à jour un modèle qui existe déjà dans la base de données. Pour mettre à jour le modèle, vous devez d'abord le récupérer, définir les propriétés à mettre à jour, puis appeler la méthode save. De même, l'horodatage updated_at sera mis à jour automatiquement, il n'est donc pas nécessaire d'attribuer manuellement la valeur : 🎜
App\Flight::withTrashed()     
   ->where('airline_id', 1)        
   ->restore();
🎜🎜Mise à jour par lots🎜 🎜Vous pouvez également mettre à jour la correspondance de plusieurs modèles pour les conditions de requête. Dans cet exemple, tous les vols avec actif et destination vers San Diego seront marqués comme retardés : 🎜
$flight->history()->restore();
🎜update accepte un tableau dont les clés sont des noms de champs et les données sont des valeurs. 🎜
🎜{note} Lors de la mise à jour par lots via Eloquent, le modèle mis à jour ne déclenchera pas les événements saved et mis à jour. Car lors des mises à jour batch, le modèle n’est jamais récupéré. 🎜🎜🎜🎜🎜🎜🎜🎜

Affectation par lots

Vous pouvez également utiliser la méthode create pour enregistrer un nouveau modèle, qui renverra une instance de modèle. Cependant, avant de l'utiliser, vous devez spécifier l'attribut fillable ou guarded sur le modèle, car tous les modèles Eloquent ne peuvent pas être attribués par lot par défaut. create 方法来保存新模型,此方法会返回模型实例。不过,在使用之前,你需要在模型上指定 fillableguarded 属性,因为所有的 Eloquent 模型都默认不可进行批量赋值。

当用户通过 HTTP 请求传入一个意外的参数,并且该参数更改了数据库中你不需要更改的字段时。比如:恶意用户可能会通过 HTTP 请求传入 is_admin  参数,然后将其传给 create 方法,此操作能让用户将自己升级成管理员。

所以,在开始之前,你应该定义好模型上的哪些属性是可以被批量赋值的。你可以通过模型上的 $fillable 属性来实现。 例如:让 Flight 模型的 name 属性可以被批量赋值:

// 单个模型实例的永久删除...
$flight->forceDelete();
// 关联模型的永久删除...
$flight->history()->forceDelete();

一旦我们设置好了可以批量赋值的属性,就可以通过 create 方法插入新数据到数据库中了。 create 方法将返回保存的模型实例:

<?php
    namespace App\Scopes;
    use Illuminate\Database\Eloquent\Scope;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\Builder;
    class AgeScope implements Scope{  
      /**
     * 把约束加到 Eloquent 查询构造中。
     *
     * @param  \Illuminate\Database\Eloquent\Builder  $builder
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return void
     */  
      public function apply(Builder $builder, Model $model)  
        {       
         $builder->where('age', '>', 200);   
         }
      }

如果你已经有一个模型实例,你可以传递一个数组给 fill 方法来赋值:

<?php
    namespace App;use App\Scopes\AgeScope;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model{  
      /**
     *  模型的 「启动」 方法.
     *
     * @return void
     */  
     protected static function boot()  
       {     
          parent::boot();        
          static::addGlobalScope(new AgeScope);  
        }
   }

保护属性

$fillable 可以看作批量赋值的「白名单」, 你也可以使用 $guarded 属性来实现。 $guarded 属性包含的是不允许批量赋值的数组。也就是说, $guarded 从功能上将更像是一个「黑名单」。注意:你只能使用 $fillable$guarded 二者中的一个,不可同时使用。下面这个例子中,除了 price 属性,其他的属性都可以批量赋值:

select * from `users` where `age` > 200

如果你想让所有属性都可以批量赋值, 你可以将 $guarded 定义成一个空数组:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\Builder;
    class User extends Model{  
      /**
     *模型的「启动」方法.
     *
     * @return void
     */  
     protected static function boot()   
      {      
        parent::boot();        
        static::addGlobalScope('age', function (Builder $builder) {  
                  $builder->where('age', '>', 200);       
                }); 
       }
   }

其他创建方法

firstOrCreate/ firstOrNew

这里有两个你可能用来批量赋值的方法: firstOrCreatefirstOrNewfirstOrCreate 方法会通过给定的 列 / 值 来匹配数据库中的数据。如果在数据库中找不到对应的模型, 则会从第一个参数的属性乃至第二个参数的属性中创建一条记录插入到数据库。

firstOrNew 方法像 firstOrCreate 方法一样尝试通过给定的属性查找数据库中的记录。不同的是,如果 firstOrNew 方法找不到对应的模型,会返回一个新的模型实例。注意 firstOrNew 返回的模型实例尚未保存到数据库中,你需要手动调用 save

Lorsque l'utilisateur transmet un paramètre inattendu via une requête HTTP et que ce paramètre modifie un champ de la base de données que vous n'avez pas besoin de modifier. Par exemple : un utilisateur malveillant peut transmettre le paramètre is_admin via une requête HTTP, puis le transmettre à la méthode create. Cette opération permet à l'utilisateur de se mettre à niveau vers un. administrateur.
Donc, avant de commencer, vous devez définir quels attributs du modèle peuvent être attribués par lots. Vous pouvez le faire via l'attribut $fillable sur le modèle. Par exemple : laissez l'attribut name du modèle Flight être attribué par lots : 🎜
User::withoutGlobalScope(AgeScope::class)->get();
🎜Une fois que nous avons configuré les attributs pouvant être attribués par lots, nous pouvons transmettre La méthode create insère de nouvelles données dans la base de données. La méthode create renverra l'instance de modèle enregistrée : 🎜
User::withoutGlobalScope('age')->get();
🎜Si vous disposez déjà d'une instance de modèle, vous pouvez transmettre un tableau à la méthode fill pour attribuer des valeurs : 🎜
// 取消所有的全局作用域...
User::withoutGlobalScopes()->get();
// 取消部分全局作用域...
User::withoutGlobalScopes([ 
   FirstScope::class, SecondScope::class
 ])->get();
🎜

Attributs protégés

🎜$fillable peut être considéré comme une "liste blanche" pour l'affectation par lots, vous pouvez également utilisez l'attribut $guarded pour y parvenir. L'attribut $guarded contient un tableau qui n'autorise pas l'affectation par lots. En d'autres termes, $guarded fonctionnera davantage comme une « liste noire ». Remarque : Vous ne pouvez utiliser qu'un seul élément parmi $fillable ou $guarded, pas les deux en même temps. Dans l'exemple suivant, à l'exception de l'attribut price, tous les autres attributs peuvent se voir attribuer des valeurs par lots : 🎜
<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model{  
      /**
     * 只查询受欢迎的用户的作用域.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */   
      public function scopePopular($query)  
        {      
          return $query->where('votes', '>', 100);   
        }    
     /**
     * 只查询 active 用户的作用域.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */  
      public function scopeActive($query)  
        {      
          return $query->where('active', 1);  
         }
      }
🎜 Si vous souhaitez que tous les attributs se voient attribuer des valeurs ​​par lots, vous pouvez modifier $guarded comme étant un tableau vide : 🎜
$users = App\User::popular()->active()->orderBy('created_at')->get();
🎜🎜
🎜🎜 Autres méthodes de création🎜
🎜

firstOrCreate/ firstOrNew

🎜Voici deux méthodes possibles pour l'affectation par lots : firstOrCreate et firstOrNew. La méthode firstOrCreate fera correspondre les données de la base de données avec la colonne/valeur donnée. Si le modèle correspondant est introuvable dans la base de données, un enregistrement sera créé à partir des attributs du premier paramètre et même des attributs du deuxième paramètre et inséré dans la base de données. 🎜🎜La méthode firstOrNew, comme la méthode firstOrCreate, tente de trouver un enregistrement dans la base de données par l'attribut donné. La différence est que si la méthode firstOrNew ne trouve pas le modèle correspondant, elle renverra une nouvelle instance de modèle. Notez que l'instance de modèle renvoyée par firstOrNew n'a pas été enregistrée dans la base de données, vous devez appeler manuellement la méthode save pour enregistrer : 🎜
$users = App\User::popular()->orWhere(function (Builder $query) {
    $query->active();
   })->get();
🎜🎜

updateOrCreate

updateOrCreate

你还可能遇到希望更新现有模型或在不存在的情况下则创建新的模型的情景。 Laravel 提供了 updateOrCreate 方法仅一个步骤就可以实现。跟 firstOrCreate 方法一样,updateOrCreate 匹配到对应模型,所以不需要调用 save() 方法:

$users = App\User::popular()->orWhere->active()->get();

删除模型

可以在模型实例上调用 delete 方法来删除实例:

<?php
    namespace App;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model{   
     /**
     * 将查询作用域限制为仅包含给定类型的用户。
     *
     * @param  \Illuminate\Database\Eloquent\Builder $query
     * @param  mixed $type
     * @return \Illuminate\Database\Eloquent\Builder
     */   
    public function scopeOfType($query, $type)  
      {      
        return $query->where('type', $type);   
       }
      }

通过主键删除模型

在上面的例子中,在调用 delete 之前需要先去数据库中查找对应的模型。事实上,如果你知道了模型的主键,你可以直接使用 destroy 方法来删除模型,而不用先去数据库中查找。 destroy 方法除了接受单个主键作为参数之外,还接受多个主键,或者使用数组,集合来保存多个主键:

$users = App\User::ofType('admin')->get();

通过查询删除模型

你也可以在模型上运行删除语句。在这个例子中,我们将删除所有标记为非活跃的航班。与批量更新一样,批量删除不会为删除的模型启动任何模型事件:

if ($post->is($anotherPost)) { 
   //
 }

{note} 通过 Eloquent 执行批量删除语句时,不会触发  deletingdeleted 模型事件。因此,在执行删除语句时,从不检索模型示例。

软删除

除了真实删除数据库记录, Eloquent  也可以「软删除」模型。软删除的模型并不是真的从数据库中删除了。事实上,是在模型上设置了 deleted_at 属性并将其值写入数据库。如果 deleted_at 值非空,代表这个模型已被软删除。如果要开启模型软删除功能,你需要在模型上使用 IlluminateDatabaseEloquentSoftDeletes trait:

<?php
    namespace App;
    use App\Events\UserSaved;
    use App\Events\UserDeleted;
    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    class User extends Authenticatable{  
      use Notifiable;   
       /**
     * 为模型事件。
     *
     * @var array
     */ 
      protected $dispatchesEvents = [    
          'saved' => UserSaved::class,        
          'deleted' => UserDeleted::class,   
           ];
       }

{tip}  SoftDeletes trait 会自动将 deleted_at 属性转换成  DateTime / Carbon 实例

当然,你需要把 deleted_at 字段添加到数据表中。 Laravel 的 数据库迁移 有创建这个字段的方法:

php artisan make:observer UserObserver --model=User

那现在,当你在模型实例上使用 delete 方法, 当前日期时间会写入 deleted_at 字段。同时,查询出来的结果也会自动排除已被软删除的记录。

你可以使用 trashedVous pouvez également rencontrer des situations dans lesquelles vous souhaitez mettre à jour un modèle existant ou créer un nouveau modèle s'il n'existe pas. Laravel fournit la méthode updateOrCreate qui peut être implémentée en une seule étape. Comme la méthode firstOrCreate, updateOrCreate correspond au modèle correspondant, il n'est donc pas nécessaire d'appeler la méthode save() :

<?php
    namespace App\Observers;
    use App\User;
    class UserObserver{   
     /**
     * 处理 User 「新建」事件。
     *
     * @param  \App\User  $user
     * @return void
     */   
      public function created(User $user) 
         {      
           //  
          }   
     /**
     * 处理 User 「更新」 事件。
     *
     * @param  \App\User  $user
     * @return void
     */   
      public function updated(User $user)  
        {      
          //   
         }   
     /**
     * 处理 User 「删除」 事件。
     *
     * @param  \App\User  $user
     * @return void
     */   
     public function deleted(User $user) 
        {   
             //   
         }
   }

Supprimer le modèle

Vous pouvez appeler la méthode delete sur l'instance du modèle pour supprimer l'instance :
<?php
    namespace App\Providers;
    use App\User;use App\Observers\UserObserver;
    use Illuminate\Support\ServiceProvider;
    class AppServiceProvider extends ServiceProvider{  
      /**
     * 启动应用服务。
     *
     * @return void
     */   
      public function boot()  
       {       
         User::observe(UserObserver::class);   
       }  
    /**
     * 注册服务提供者。
     *
     * @return void
     */  
     public function register() 
        {      
          //   
         }
      }

Supprimer le modèle par clé primaire
Dans l'exemple ci-dessus, vous devez accéder à la base de données avant Appel à delete Trouver le modèle correspondant dans . En fait, si vous connaissez la clé primaire d'un modèle, vous pouvez directement utiliser la méthode destroy pour supprimer le modèle sans le rechercher au préalable dans la base de données. En plus d'accepter une seule clé primaire comme paramètre, la méthode destroy accepte également plusieurs clés primaires, ou utilise un tableau ou une collection pour enregistrer plusieurs clés primaires :
rrreee
🎜🎜Supprimer le modèle via une requête🎜Vous pouvez également exécuter des instructions de suppression sur le modèle. Dans cet exemple, nous supprimerons tous les vols marqués comme inactifs. Comme la mise à jour par lots, la suppression par lots ne déclenchera aucun événement de modèle pour le modèle supprimé : 🎜rrreee
🎜{note} Lors de l'exécution d'une instruction de suppression par lots via Eloquent, la suppression et le ne seront pas déclenché. événement de modèle supprimé. Par conséquent, lors de l’exécution d’une instruction delete, les exemples de modèles ne sont jamais récupérés. 🎜
🎜🎜🎜
🎜🎜Suppression logicielle🎜🎜En plus de supprimer réellement les enregistrements de la base de données, Eloquent peut également Modèle "suppression logicielle" Supprimer ". Un modèle supprimé de manière réversible n’est pas réellement supprimé de la base de données. En fait, l'attribut deleted_at est défini sur le modèle et sa valeur est écrite dans la base de données. Si la valeur deleted_at n'est pas vide, cela signifie que le modèle a été supprimé de manière logicielle. Si vous souhaitez activer la fonction de suppression logicielle du modèle, vous devez utiliser le trait IlluminateDatabaseEloquentSoftDeletes sur le modèle : 🎜rrreee
🎜{tip} Le trait SoftDeletes sera automatiquement supprimer l'attribut deleted_at< /code> est converti en une instance DateTime / Carbon🎜
🎜Bien sûr, vous devez ajouter le champ delete_at à la table de données. La migration de la base de données de Laravel a une méthode pour créer ce champ : 🎜rrreee🎜Maintenant, lorsque vous utilisez la méthode delete sur l'instance du modèle, la date et l'heure actuelles seront écrites dans le deleted_at. Dans le même temps, les résultats de la requête excluront automatiquement les enregistrements qui ont été supprimés de manière logicielle. 🎜🎜Vous pouvez utiliser la méthode trashed pour vérifier si le modèle actuel est supprimé de manière logicielle : 🎜rrreee🎜🎜🎜🎜🎜🎜🎜Interrogez le modèle supprimé de manière logicielle🎜🎜🎜

Y compris les modèles supprimés de manière logicielle

Comme mentionné précédemment, les résultats de la requête excluront automatiquement les résultats supprimés de manière logicielle. Bien sûr, vous pouvez utiliser la méthode withTrashed pour obtenir des modèles incluant des modèles supprimés de manière logicielle : withTrashed 方法来获取包括软删除模型在内的模型:

rrreee

withTrashed 方法也可以用在 关联 查询:

rrreee

检索软删除模型

onlyTrashed 方法   获取已软删除的模型:

rrreee

恢复软删除模型

有时会对软删除模型进行 「撤销」,在已软删除的数据上使用 restore 方法即可恢复到有效状态:

rrreee

你也可以在查询中使用 restore 方法,从而快速恢复多个模型。和其他批量」操作一样,这个操作不会触发模型的任何事件:

rrreee

类似 withTrashed 方法, restore 方法也用在 关联上:

rrreee

永久删除

要真实删除数据时,使用 forceDelete 方法即可:

rrreee

查询作用域

全局作用域

全局作用域可以给模型的查询都添加上约束。Laravel 的  软删除 功能就是利用此特性从数据库中获取 「未删除」的模型。 你可以编写你自己的全局作用域,很简单、方便的为每个模型查询都加上约束条件:

编写全局作用域

编写全局作用域很简单。定义一个实现 IlluminateDatabaseEloquentScope 接口的类,并实现 apply 这个方法。 根据你的需求,在 apply 方法中加入查询的 where 条件:

rrreee

{tip} 如果需要在 select 语句里添加字段,应使用 addSelect 方法,而不是 select 方法。 这将有效防止无意中替换现有 select 语句的情况。

应用全局作用域

要将全局作用域分配给模型,需要重写模型的 boot 方法并使用 addGlobalScope 方法:

rrreee

添加作用域后,对 User::all()rrreee

La méthode withTrashed peut également être utilisée dans des requêtes associées :
rrreee

Récupérer les modèles supprimés de manière logicielle

onlyTrashed Méthode uniquement Récupérer les modèles supprimés de manière logicielle :

rrreee
Restaurer le modèle supprimé de manière logicielle🎜🎜Parfois, le modèle supprimé de manière logicielle est "annulé", et vous pouvez utiliser la méthode restaurer sur les données supprimées de manière logicielle pour restaurez-le à l'état valide : 🎜rrreee🎜Vous pouvez également utiliser la méthode restore dans une requête pour restaurer rapidement plusieurs modèles. Comme les autres opérations batch, cette opération ne déclenchera aucun événement dans le modèle : 🎜rrreee🎜Similaire à la méthode withTrashed, la méthode restore est également utilisée sur les associations : 🎜rrreee
🎜🎜Suppression permanente🎜🎜Pour supprimer réellement des données, utilisez la méthode forceDelete : 🎜rrreee🎜🎜
🎜

Portée de la requête

🎜🎜
🎜

Portée globale

🎜La portée globale peut ajouter des contraintes aux requêtes de modèle. La fonction de suppression logicielle de Laravel utilise cette fonctionnalité pour obtenir des modèles "non supprimés" de la base de données. Vous pouvez écrire votre propre portée globale et ajouter des contraintes à chaque requête de modèle très simplement et facilement : 🎜
🎜🎜Écrire une portée globale🎜🎜 Écrire une portée globale est facile. Définissez une classe qui implémente l'interface IlluminateDatabaseEloquentScope et implémentez la méthode apply. Selon vos besoins, ajoutez la condition where de la requête dans la méthode apply : 🎜rrreee
🎜{tip} Si vous devez ajouter des champs dans l'instruction select , vous devez utiliser la méthode < code>addSelect, et non la méthode select. Cela empêchera efficacement le remplacement par inadvertance des instructions select existantes. 🎜
🎜🎜Appliquer la portée globale🎜🎜Pour attribuer la portée globale à un modèle, vous devez remplacer le boot du modèle. et utilisez la méthode addGlobalScope : 🎜rrreee🎜Après avoir ajouté la portée, la requête pour User::all() générera l'instruction de requête SQL suivante : 🎜rrreee🎜🎜 🎜Portée globale anonyme 🎜🎜Eloquent permet également l'utilisation de fermetures pour définir des portées globales, il n'est donc pas nécessaire d'écrire une classe distincte pour une portée simple : 🎜rrreee🎜🎜

Annuler la portée globale

Si vous devez annuler la portée globale de la requête actuelle, vous devez utiliser la méthode sansGlobalScope. Cette méthode n'accepte que le nom de classe de portée globale comme seul paramètre : withoutGlobalScope 方法。 该方法仅接受全局作用域类名作为它唯一的参数:

rrreee

或者,如果使用闭包定义全局作用域的话:

rrreee

如果你需要取消部分或者全部的全局作用域的话,需要使用  withoutGlobalScopes 方法:

rrreee

本地作用域

本地作用域允许定义通用的约束集合以便在应用程序中重复使用。例如,你可能经常需要获取所有 「流行」的用户。 要定义这样一个范围,只需要在对应的 Eloquent 模型方法前添加 scope 前缀:

作用域总是返回一个查询构造器实例:

rrreee

使用本地作用域

一旦定义了作用域,就可以在查询该模型时调用作用域方法。不过,在调用这些方法时不必包含 scope 前缀。甚至可以链式调用多个作用域,例如:

rrreee

借助 or 查询运行符整合多个 Eloquent 模型,可能需要使用闭包回调:

rrreee

因为这样可能会有点麻烦,Laravel 提供了「高阶的」 orWhere 方法,它允许你在链式调用作用域时不使用闭包:

rrreee

动态作用域

有时可能地希望定义一个可以接受参数的作用域。把额外参数传递给作用域就可以达到此目的。作用域参数要放在 $query 参数之后:

rrreee

这样就可以在调用作用域时传递参数了:

rrreee

模型比较

有时可能需要判断两个模型是否「相同」。 isrrreee

Ou, si une fermeture est utilisée pour définir la portée globale :

rrreee Si vous devez annuler une partie ou la totalité de la portée globale, vous devez utiliser Méthode withoutGlobalScopes : rrreee

🎜

Portées locales

🎜 La portée locale vous permet de définir un ensemble commun de contraintes à réutiliser dans une application. Par exemple, vous devrez peut-être souvent obtenir tous les utilisateurs « populaires ». Pour définir une telle portée, ajoutez simplement le préfixe scope avant la méthode du modèle Eloquent correspondante : 🎜🎜Scope renvoie toujours une instance du générateur de requêtes : 🎜rrreee
🎜🎜Utiliser des portées locales🎜🎜Une fois qu'une portée est définie, les méthodes de portée peuvent être appelées lors de l'interrogation de ce modèle. Cependant, il n'est pas nécessaire d'inclure le préfixe scope lors de l'appel de ces méthodes. Vous pouvez même chaîner des appels vers plusieurs portées, par exemple : 🎜rrreee🎜Utilisez l'exécuteur de requêtes ou pour intégrer plusieurs modèles Eloquent. Vous devrez peut-être utiliser des rappels de fermeture : 🎜rrreee🎜Parce que cela peut être un peu. gênant, Laravel fournit la méthode orWhere "d'ordre supérieur", qui vous permet d'enchaîner les portées d'appel sans utiliser de fermetures : 🎜rrreee
🎜🎜 Portée dynamique🎜🎜Parfois, vous souhaiterez peut-être définir une portée qui accepte des paramètres. Ceci peut être réalisé en transmettant des paramètres supplémentaires à la portée. Les paramètres de scope doivent être placés après le paramètre $query : 🎜rrreee🎜 De cette façon, vous pouvez transmettre des paramètres lors de l'appel du scope : 🎜rrreee🎜🎜🎜
🎜

Comparaison de modèles

🎜Parfois, il peut être nécessaire de déterminer si deux modèles sont "identiques". La méthode is peut être utilisée pour vérifier rapidement si deux modèles ont les mêmes clés primaires, tables et connexions à la base de données : 🎜rrreee🎜🎜🎜🎜🎜🎜

Événements

Le modèle Eloquent déclenche plusieurs événements, vous permettant de vous connecter aux nœuds suivants du cycle de vie du modèle : récupéré, création, créé, mise à jour, mis à jour, enregistrement, enregistré, suppression, supprimé< /code>, restauration et restauré. Les événements vous permettent d'exécuter du code chaque fois qu'un modèle spécifique est enregistré ou mis à jour dans la base de données. Chaque événement accepte une instance de modèle via son constructeur. L'événement retrievedcreatingcreatedupdatingupdatedsavingsaveddeletingdeletedrestoringrestored。事件允许你每当特定模型保存或更新数据库时执行代码。每个事件通过其构造器接受模型实例。

retrieved 事件在现有模型从数据库中查找数据时触发。当新模型每一次保存时, creatingcreated 事件被触发。如果数据库中已经存在模型并且调用了 save 方法, updating / updated 事件被触发。这些情况下, saving / saved 事件也被触发。

{note} 通过 Eloquent 进行批量更新时,被更新模型的 savedupdated 事件不会被触发。这是因为批量更新时,并没有真的获取模型。

首先,在 Eloquent 模型上定义一个 $dispatchesEvents 属性,将 Eloquent 模型生命周期的几个节点映射到你自己的 event 类 :

rrreee

定义并且映射了 Eloquent 事件,就可以使用 event 监听器 listeners 处理这些事件了。

观察者

定义观察者

如果在一个模型上监听了多个事件,可以使用观察者来将这些监听器组织到一个单独的类中。观察者类的方法名映射到你希望监听的 Eloquent 事件。 这些方法都以模型作为其唯一参数。 make:observer Artisan 命令可以快速建立新的观察者类:

rrreee

此命令将在 App/Observers 文件夹放置新的观察者类。如果这个目录不存在,Artisan 将替你创建。使用如下方式开启观察者:

rrreee

在你希望观察的模型上使用 observe 方法注册观察者。也可以在服务提供者的 boot 方法注册观察者。下面是在 AppServiceProvider

retrieved est déclenché lorsqu'un modèle existant recherche des données dans la base de données. Chaque fois qu'un nouveau modèle est enregistré, les événements creating et created sont déclenchés. Si le modèle existe déjà dans la base de données et que la méthode save est appelée, les événements updating / updated sont déclenchés. Dans ces cas, les événements save / saved sont également déclenchés. Tout d'abord, définissez un attribut $dispatchesEvents sur le modèle Eloquent pour mapper plusieurs nœuds du cycle de vie du modèle Eloquent à votre propre classe d'événements :
rrreee🎜 définit et mappe les événements Eloquent, vous peut utiliser des écouteurs d'événements pour gérer ces événements. 🎜🎜🎜🎜
🎜

Observateurs

🎜

Définir les observateurs

🎜Si vous écoutez plusieurs événements sur un modèle, vous pouvez utiliser des observateurs pour organiser ces auditeurs dans une classe distincte. Les noms de méthode de la classe d'observateur correspondent aux événements Eloquent que vous souhaitez écouter. Ces méthodes prennent toutes le modèle comme seul paramètre. make:observer La commande Artisan peut créer rapidement une nouvelle classe d'observateur : 🎜rrreee🎜Cette commande placera une nouvelle classe d'observateur dans le dossier App/Observers. Si ce répertoire n'existe pas, Artisan le créera pour vous. Utilisez la méthode suivante pour activer un observateur : 🎜rrreee🎜Utilisez la méthode observer pour enregistrer un observateur sur le modèle que vous souhaitez observer. Les observateurs peuvent également être enregistrés dans la méthode boot du fournisseur de services. Voici un exemple d'enregistrement d'un observateur dans AppServiceProvider : 🎜rrreee🎜Cet article est apparu pour la première fois sur le site Web 🎜LearnKu.com🎜. 🎜🎜