Eloquent ORM #

一、Eloquent概述 #

1.1 什么是Eloquent #

Eloquent是Laravel内置的ORM(对象关系映射),使用ActiveRecord模式,让数据库操作变得优雅简单。

php
// 每个Eloquent模型对应一张数据表
class User extends Model
{
    //
}

// 使用模型操作数据库
$users = User::all();
$user = User::find(1);
$user->name = 'John';
$user->save();

1.2 创建模型 #

bash
php artisan make:model User

# 同时创建迁移文件
php artisan make:model User --migration
# 或
php artisan make:model User -m

1.3 模型约定 #

php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // 指定表名(默认使用类名的复数形式)
    protected $table = 'my_users';

    // 指定主键(默认为id)
    protected $primaryKey = 'user_id';

    // 禁用自增
    public $incrementing = false;

    // 主键类型
    protected $keyType = 'string';

    // 禁用时间戳
    public $timestamps = false;

    // 时间戳格式
    protected $dateFormat = 'U';

    // 默认属性值
    protected $attributes = [
        'active' => 1,
    ];
}

二、查询数据 #

2.1 获取所有数据 #

php
$users = User::all();

2.2 根据主键查询 #

php
// 查找单个
$user = User::find(1);

// 查找或抛出异常
$user = User::findOrFail(1);
$user = User::where('email', 'john@example.com')->firstOrFail();

// 查找多个
$users = User::find([1, 2, 3]);

2.3 条件查询 #

php
$users = User::where('active', 1)->get();

$user = User::where('email', 'john@example.com')->first();

// 链式调用
$users = User::where('active', 1)
    ->orderBy('name')
    ->take(10)
    ->get();

2.4 获取集合 #

php
$users = User::where('active', 1)->get();

// 遍历
foreach ($users as $user) {
    echo $user->name;
}

2.5 分块处理 #

php
User::chunk(200, function ($users) {
    foreach ($users as $user) {
        // 处理用户
    }
});

2.6 游标遍历 #

php
foreach (User::cursor() as $user) {
    // 处理用户
}

三、插入数据 #

3.1 创建模型 #

php
// 方式一
$user = new User;
$user->name = 'John';
$user->email = 'john@example.com';
$user->save();

// 方式二
$user = User::create([
    'name' => 'John',
    'email' => 'john@example.com',
]);

3.2 批量赋值 #

php
class User extends Model
{
    // 可批量赋值的字段
    protected $fillable = ['name', 'email', 'password'];

    // 不可批量赋值的字段
    protected $guarded = ['id', 'is_admin'];
}

// 使用create方法
$user = User::create($request->all());

// 使用firstOrCreate
$user = User::firstOrCreate(['email' => 'john@example.com']);

// 使用firstOrNew(不保存)
$user = User::firstOrNew(['email' => 'john@example.com']);

// 使用updateOrCreate
$user = User::updateOrCreate(
    ['email' => 'john@example.com'],
    ['name' => 'John Doe']
);

四、更新数据 #

4.1 更新模型 #

php
$user = User::find(1);
$user->name = 'Jane';
$user->save();

4.2 批量更新 #

php
User::where('active', 0)
    ->update(['active' => 1]);

4.3 更新时间戳 #

php
$user->touch();

五、删除数据 #

5.1 删除模型 #

php
$user = User::find(1);
$user->delete();

5.2 根据主键删除 #

php
User::destroy(1);
User::destroy([1, 2, 3]);

5.3 条件删除 #

php
User::where('active', 0)->delete();

5.4 软删除 #

php
class User extends Model
{
    use SoftDeletes;
}

// 迁移文件
Schema::table('users', function (Blueprint $table) {
    $table->softDeletes();
});

// 使用
$user->delete();  // 软删除
$user->forceDelete();  // 强制删除
$user->restore();  // 恢复

// 查询
$users = User::withTrashed()->get();  // 包含软删除
$users = User::onlyTrashed()->get();  // 只查软删除

六、模型关联 #

6.1 一对一 #

php
class User extends Model
{
    public function phone()
    {
        return $this->hasOne(Phone::class);
    }
}

class Phone extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

// 使用
$phone = $user->phone;
$user = $phone->user;

6.2 一对多 #

php
class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

// 使用
$posts = $user->posts;
$user = $post->user;

6.3 多对多 #

php
class User extends Model
{
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
}

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
}

// 使用
$roles = $user->roles;

// 附加
$user->roles()->attach($roleId);

// 分离
$user->roles()->detach($roleId);

// 同步
$user->roles()->sync([1, 2, 3]);

// 切换
$user->roles()->toggle([1, 2, 3]);

6.4 远程一对多 #

php
class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}

6.5 多态关联 #

php
class Post extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

class Video extends Model
{
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

// 使用
$comments = $post->comments;
$commentable = $comment->commentable;

七、预加载 #

7.1 N+1问题 #

php
// 不推荐:N+1问题
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->user->name;  // 每次循环都查询一次
}

// 推荐:预加载
$posts = Post::with('user')->get();
foreach ($posts as $post) {
    echo $post->user->name;  // 不再额外查询
}

7.2 预加载多个关联 #

php
$posts = Post::with(['user', 'comments'])->get();

7.3 嵌套预加载 #

php
$posts = Post::with('comments.user')->get();

7.4 条件预加载 #

php
$posts = Post::with(['comments' => function ($query) {
    $query->where('approved', 1);
}])->get();

7.5 延迟预加载 #

php
$posts = Post::all();

// 之后预加载
$posts->load('user', 'comments');

八、访问器和修改器 #

8.1 访问器 #

php
class User extends Model
{
    public function getNameAttribute($value)
    {
        return ucfirst($value);
    }

    // 定义虚拟属性
    public function getFullNameAttribute()
    {
        return $this->first_name . ' ' . $this->last_name;
    }
}

// 使用
echo $user->name;       // 自动调用访问器
echo $user->full_name;  // 虚拟属性

8.2 修改器 #

php
class User extends Model
{
    public function setPasswordAttribute($value)
    {
        $this->attributes['password'] = bcrypt($value);
    }
}

// 使用
$user->password = 'secret';  // 自动加密

8.3 属性转换 #

php
class User extends Model
{
    protected $casts = [
        'options' => 'array',
        'active' => 'boolean',
        'created_at' => 'datetime',
        'deleted_at' => 'immutable_datetime',
        'price' => 'decimal:2',
    ];
}

// 使用
$user->options = ['key' => 'value'];  // 自动转JSON
$options = $user->options;  // 自动转数组

九、查询作用域 #

9.1 本地作用域 #

php
class User extends Model
{
    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }

    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

// 使用
$users = User::active()->get();
$users = User::ofType('admin')->get();

9.2 全局作用域 #

php
class SoftDeletingScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->whereNull($model->getQualifiedDeletedAtColumn());
    }
}

// 注册
protected static function booted()
{
    static::addGlobalScope(new SoftDeletingScope);
}

// 移除
User::withoutGlobalScope(SoftDeletingScope::class)->get();

十、模型事件 #

10.1 事件类型 #

事件 说明
retrieved 从数据库获取后
creating 创建前
created 创建后
updating 更新前
updated 更新后
saving 保存前
saved 保存后
deleting 删除前
deleted 删除后
restoring 恢复前
restored 恢复后

10.2 定义事件监听 #

php
class User extends Model
{
    protected static function booted()
    {
        static::created(function ($user) {
            // 用户创建后执行
        });

        static::updating(function ($user) {
            // 用户更新前执行
        });
    }
}

10.3 使用Observer #

bash
php artisan make:observer UserObserver --model=User
php
// app/Observers/UserObserver.php
class UserObserver
{
    public function created(User $user)
    {
        //
    }

    public function updated(User $user)
    {
        //
    }
}

// 注册
// app/Providers/AppServiceProvider.php
public function boot()
{
    User::observe(UserObserver::class);
}

十一、总结 #

11.1 核心概念 #

概念 说明
模型 对应数据表
关联 表之间的关系
访问器 获取属性时转换
修改器 设置属性时转换
作用域 可复用的查询条件
事件 模型生命周期事件

11.2 下一步 #

掌握了Eloquent ORM后,让我们继续学习 数据库迁移,了解如何管理数据库结构!

最后更新:2026-03-28