Eloquent: 入门
简介
Laravel 的 Eloquent ORM 提供了漂亮、简洁的 ActiveRecord 实现来和数据库交互。每个数据库表都有一个对应的「模型」用来与该表交互。你可以通过模型查询数据表中的数据,并将新记录添加到数据表中。
在开始之前,请确保在 config/database.php
中配置数据库连接。更多关于数据库的配置信息,请查看 文档。
定义模型
首先,创建一个 Eloquent 模型,生成的模型通常放在 app
目录中,但你可以通过 composer.json
随意地将它们放在可被自动加载的地方。所有的 Eloquent 模型都继承了 Illuminate\Database\Eloquent\Model
类。
创建模型实例的最简单方法是使用 Artisan 命令 make:model
:
php artisan make:model User
如果要在生成模型时生成 数据库迁移,可以使用 --migration
或 -m
选项:
php artisan make:model User --migration
php artisan make:model User -m
Eloquent 模型约定
现在,我们来看一个 Flight
模型类的例子,我们将会用它从 flights
数据表中检索和存储信息:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
数据表名称
请注意,我们并没有告诉 Eloquent,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
。 如果使用的是非递增或者非数字的主键,则必须在模型上设置 public $incrementing = false
。如果主键不是一个整数,则应该在模型上设置 protected $keyType = string
。
时间戳
默认情况下,Eloquent 会默认数据表中存在 created_at
和 updated_at
这两个字段。如果你不需要这两个字段,则需要在模型内将 $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_AT
和 UPDATED_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';
}
检索多个模型
创建完模 型 及其关联的数据表 之后,就可以开始从数据库中检索数据。可把每个 Eloquent 模型想像成强大的 查询构造器,它让你可以流畅地查询与该模型相关联的数据库表。例如:
<?php
use App\Flight;
$flights = App\Flight::all();
foreach ($flights as $flight) {
echo $flight->name;
}
添加其他约束
Eloquent 的 all
方法会返回模型表中所有的结果。由于每个 Eloquent 模型都可以当作一个 查询构造器,因此你还可以在查询中添加约束,然后使用 get
方法来获取结果:
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
Eloquent 模型是查询构造器,因此你应当去阅读 查询构造器 提供的所有方法,以便你可以在 Eloquent 查询中使用。
集合
使用 Eloquent 中的方法比如 all
和 get
可以检索多个结果,并且会返回一个 Illuminate\Database\Eloquent\Collection
实例。Collection
类提供了 很多辅助函数 来处理Eloquent 结果。
$flights = $flights->reject(function ($flight) {
return $flight->cancelled;
});
你也可以像数组一样简单地来遍历集合:
foreach ($flights as $flight) {
echo $flight->name;
}
分块结果
如果你需要处理数千个 Eloquent 记录,可以使用 chunk
命令。chunk
方法会检索 Eloquent 模型的「分块」,将它们提供给指定的 Closure
进行处理。在处理大型结果集时,使用 chunk
方法可节省内存:
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
传递到方法的第一个参数是希望每个「分块」接收的数据量。闭包则被作为第二个参数传递,它会在每次执行数据库查询传递每个块时被调用。
使用游标
cursor
允许你使用游标来遍历数据库数据,该游标只执行一个查询。处理大量数据时,可以使用 cursor
方法可以大幅度减少内存的使用量:
foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
//
}
检索单个模型/集合
除了从指定的数据表检索所有记录外,你也可以通过 find
或 first
方法来检索单条记录。这些方法不是返回一组模型,而是返回一个模型实例:
// 通过主键取回一个模型...
$flight = App\Flight::find(1);
// 取回符合查询限制的第一个模型 ...
$flight = App\Flight::where('active', 1)->first();
你也可以用主键数组为参数调用 find
方法,它将返回匹配记录的集合:
$flights = App\Flight::find([1, 2, 3]);
「找不到」异常
如果你希望在找不到模型时抛出异常,可以使用 findOrFail
以及 firstOrFail
方法。这些方法会检索查询的第一个结果。如果没有找到相应结果,就会抛出一个 Illuminate\Database\Eloquent\ModelNotFoundException
:
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
如果没有对异常进行捕获,则会自动返回 HTTP 404
响应给用户。也就是说,在使用这些方法时,不需要另外写个检查来返回 404
响应:
Route::get('/api/flights/{id}', function ($id) {
return App\Flight::findOrFail($id);
});
检索集合
你还可以使 用 查询构造器 提供的 count
、sum
、max
以及其它 聚合函数。这些方法只会返回适当的标量值而不是整个模型实例:
$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');
插入 & 更新模型
插入
要在数据库中创建新记录,只需创建一个新的模型实例,并在模型上设置属性,然后调用 save
方法:
<?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();
}
}
在这个例子中,我们把来自 HTTP 请求中的 name
参数简单地指定给 App\Flight
模型实例的 name
属性。当我们调用 save
方法时,就会添加一条记录到数据库中。created_at
以及 updated_at
时间戳将在 save
方法被调用时会被自动设置,因此我们不需要去手动设置它们。
更新
save
方法也可以用来更新数据库中已经存在的模型。要更新模型,则须先检索模型,再设置要更新的属性,然后再调用 save
方法。同样的,updated_at
时间戳将会被自动更新,所以我们不需要手动设置它的值:
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();