当从数据库请求数据时,模型将主要使用 get 或 first 方法来检索值,这分别取决于您是希望检索多个模型还是检索单个模型。源自模型的查询将返回一个 October\Rain\Database\Builder 实例。
一旦您创建了模型以及其关联的数据库表,您就可以开始从数据库中检索数据了。将每个模型视为一个强大的查询构建器,它允许您查询与该模型关联的数据库表。
$flights = Flight::all();如果你有一个模型实例,你可以通过访问相应的属性来访问模型的列值。例如,让我们遍历通过查询返回的每个 Flight 实例,并输出 name 列的值。
foreach ($flights as $flight) {
echo $flight->name;
}all 方法将返回模型表中的所有结果。由于每个模型都充当 查询构建器,你还可以向查询添加约束,然后使用 get 方法检索结果:
$flights = Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();由于模型是查询构建器,您应该熟悉 查询构建器 上所有可用的方法。您可以在模型查询中使用这些方法中的任何一个。
对于 all 和 get 等检索多个结果的方法,将返回一个 Collection 实例。这个类提供 多种有用的方法 用于处理你的结果。当然,你可以简单地像数组一样遍历这个集合。
foreach ($flights as $flight) {
echo $flight->name;
}If you need to process thousands of records, use the chunk command. The chunk method will retrieve a "chunk" of models, feeding them to a given Closure for processing. Using the chunk method will conserve memory when working with large result sets.
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});传递给方法的第一个参数是你希望每个“块”接收的记录数量。 作为第二个参数传递的闭包将为从数据库中检索到的每个块调用。
除了检索给定表中的所有记录之外,您还可以使用 find 和 first 检索单条记录。这些方法不返回模型集合,而是返回单个模型实例。
// Retrieve a model by its primary key
$flight = Flight::find(1);
// Retrieve the first model matching the query constraints
$flight = Flight::where('active', 1)->first();有时,如果未找到模型,您可能希望抛出异常。这在路由或控制器中特别有用。findOrFail 和 firstOrFail 方法将检索查询的第一个结果。然而,如果未找到任何结果,将抛出 Illuminate\Database\Eloquent\ModelNotFoundException。
$model = Flight::findOrFail(1);
$model = Flight::where('legs', `>`, 100)->firstOrFail();当 开发 API 时,如果未捕获到异常,一个 404 HTTP 响应会自动发送回用户,因此在使用这些方法时,无需编写显式检查来返回 404 响应。
Route::get('/api/flights/{id}', function ($id) {
return Flight::findOrFail($id);
});您还可以使用 count, sum, max, 以及其他 聚合函数 由查询构建器提供. 这些方法返回相应的标量值而不是完整的模型实例:
$count = Flight::where('active', 1)->count();
$max = Flight::where('active', 1)->max('price');插入和更新数据是模型的基石功能,与传统的 SQL 语句相比,它使这个过程轻松自如。
要在数据库中创建新记录,只需创建新的模型实例,设置模型的属性,然后调用 save 方法:
$flight = new Flight;
$flight->name = 'Sydney to Canberra';
$flight->save();在此示例中,我们只需创建一个新的 Flight 模型实例,并设置 name 属性。当我们调用 save 方法时,一条记录将被插入到数据库中。created_at 和 updated_at 时间戳也将自动设置,因此无需手动设置它们。
该 save 方法也可用于更新数据库中已存在的模型。要更新模型,您应该先检索它,设置您希望更新的任何属性,然后调用 save 方法。同样,updated_at 时间戳将自动更新,因此无需手动设置其值:
$flight = Flight::find(1);
$flight->name = 'Darwin to Adelaide';
$flight->save();更新也可以针对与给定查询匹配的任意数量的模型执行。在此示例中,所有状态为 active 且 destination 为 San Diego 的航班都将被标记为延误:
Flight::where('is_active', true)
->where('destination', 'Perth')
->update(['delayed' => true]);该 update 方法期望一个表示要更新的列的列与值对的数组。
您也可以使用 create 方法在单行中保存新的模型。插入的模型实例将会从该方法返回给您。然而,在这样做之前,您需要在模型上指定 fillable 或 guarded 属性,因为所有模型都防范批量赋值。请注意,fillable 或 guarded 都不影响后端表单的提交,仅影响 create 或 fill 方法的使用。
批量赋值漏洞发生在用户通过请求传递了一个意想不到的 HTTP 参数时,并且该参数更改了您数据库中您未预期的列。例如,恶意用户可能会通过 HTTP 请求发送一个 is_admin 参数,该参数随后被映射到您模型的 create 方法上,从而允许用户将自己提升为管理员。
首先,您应该定义哪些模型属性希望其可批量赋值。您可以通过使用模型上的 $fillable 属性来完成此操作。例如,我们将 Flight 模型的 name 属性设置为可批量赋值:
class Flight extends Model
{
/**
* @var array fillable attributes that are mass assignable.
*/
protected $fillable = ['name'];
}一旦我们使属性可批量赋值,我们就可以使用 create 方法在数据库中插入一条新记录。create 方法返回已保存的模型实例:
$flight = Flight::create(['name' => 'Flight 10']);尽管 $fillable 作为可批量赋值属性的 "允许列表",但您也可以选择使用 $guarded。$guarded 属性应包含一个您不希望被批量赋值的属性数组。所有不在该数组中的其他属性都将可批量赋值。因此,$guarded 的作用类似于一个 "阻止列表"。当然,您应该使用 $fillable 或 $guarded 其中之一,而不是两者都用:
class Flight extends Model
{
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = ['price'];
}在上面的示例中,所有属性**除了price**都将是可批量赋值的。
有时您可能希望只实例化模型的一个新实例。您可以使用 make 方法来做到这一点。make 方法将简单地返回一个新实例,而不会保存或创建任何内容。
$flight = Flight::make(['name' => 'Flight 10']);
// Functionally the same as...
$flight = new Flight;
$flight->fill(['name' => 'Flight 10']);还有另外两种方法,你可以通过批量赋值属性来创建模型:firstOrCreate 和 firstOrNew。此 firstOrCreate 方法会尝试使用给定的列/值对来查找数据库记录。如果模型在数据库中找不到,则会使用给定的属性插入一条记录。
此 firstOrNew 方法,与 firstOrCreate 类似,将尝试在数据库中查找与给定属性匹配的记录。但是,如果未找到模型,将返回一个新的模型实例。请注意,由 firstOrNew 返回的模型尚未持久化到数据库。您需要手动调用 save 来持久化它:
// Retrieve the flight by the attributes, otherwise create it
$flight = Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve the flight by the attributes, or instantiate a new instance
$flight = Flight::firstOrNew(['name' => 'Flight 10']);要删除模型,在模型实例上调用 delete 方法:
$flight = Flight::find(1);
$flight->delete();在上面的例子中,我们在调用 delete 方法之前从数据库中检索模型。但是,如果你知道模型的主键,你可以不检索模型就删除模型。为此,请调用 destroy 方法:
Flight::destroy(1);
Flight::destroy([1, 2, 3]);
Flight::destroy(1, 2, 3);你也可以针对一组模型运行删除查询。在此示例中,我们将删除所有被标记为不活跃的航班:
$deletedRows = Flight::where('active', 0)->delete();值得一提的是 模型事件 在直接通过查询删除记录时将不会触发。
作用域允许您定义一组可在整个应用程序中轻松重用的常用约束。 例如,您可能需要频繁检索所有被认为是“热门”的用户。 要定义一个作用域,只需在模型方法前加上 scope。
class User extends Model
{
/**
* scopePopular query to only include popular users.
*/
public function scopePopular($query)
{
return $query->where('votes', `>`, 100);
}
/**
* scopeActive query to only include active users.
*/
public function scopeActive($query)
{
return $query->where('is_active', 1);
}
}一旦作用域被定义,你就可以在查询模型时调用作用域方法。但是,在调用方法时,你不需要包含 scope 前缀。你甚至可以链式调用各种作用域,例如:
$users = User::popular()->active()->orderBy('created_at')->get();有时你可能希望定义一个接受参数的作用域。要开始,只需将你的额外参数添加到作用域中。作用域参数应在 $query 参数之后定义:
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*/
public function scopeApplyType($query, $type)
{
return $query->where('type', $type);
}
}现在你可以在调用 scope 时传递参数:
$users = User::applyType('admin')->get();