Laravel Eloquent ORM教程

2026-09-02 3

Laravel 项目里,操作数据库不一定要直接写大量 SQL。Eloquent ORM 提供了一种更接近面向对象的写法,可以把数据表映射成模型,让开发者通过模型完成查询、新增、修改、删除和关联数据读取。对于中小型后台、内容系统、接口项目和管理平台来说,Eloquent 是 Laravel 开发中非常常用的一部分。

一、Eloquent ORM 是什么

ORM 是 Object Relational Mapping 的缩写,意思是对象关系映射。简单说,就是把数据库表和 PHP 类对应起来,把表中的一行数据对应成一个模型对象。

例如,数据库中有一张 posts 表,就可以创建一个 Post 模型。之后查询文章时,不必每次手写 SQL,可以直接使用:

$posts = Post::where('status', 1)->get();

这种写法更符合 Laravel 的开发习惯,也更容易和控制器、服务层、API 返回数据结合。

二、创建 Eloquent 模型

可以使用 Artisan 命令创建模型:

php artisan make:model Post

执行后会生成:

app/Models/Post.php

模型文件示例:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $fillable = [
        'title',
        'content',
        'status',
    ];
}

$fillable 用来定义允许批量赋值的字段。这样在创建或更新数据时,可以避免不希望被用户提交修改的字段被写入。

如果想同时创建模型和迁移文件,可以执行:

php artisan make:model Post -m

三、模型和数据表的对应关系

Laravel 默认会把模型类名转换为复数形式的数据表名。

例如:

  1. Post 模型默认对应 posts 表。
  2. User 模型默认对应 users 表。
  3. Category 模型默认对应 categories 表。

如果数据表名称不符合 Laravel 默认规则,可以在模型中指定:

class Post extends Model
{
    protected $table = 'article_posts';
}

如果主键不是 id,也可以指定:

protected $primaryKey = 'post_id';

如果表里没有 created_atupdated_at 字段,可以关闭时间戳:

public $timestamps = false;

四、使用 Eloquent 查询数据

Eloquent 提供了常用的数据查询方法。

查询全部数据:

$posts = Post::all();

按条件查询:

$posts = Post::where('status', 1)->get();

查询单条数据:

$post = Post::find(1);

如果找不到数据就抛出异常:

$post = Post::findOrFail(1);

排序查询:

$posts = Post::where('status', 1)
    ->orderBy('created_at', 'desc')
    ->get();

分页查询:

$posts = Post::where('status', 1)->paginate(10);

在列表页、后台管理页和 API 数据接口中,分页查询非常常用。

五、新增数据

新增数据可以使用 create 方法:

$post = Post::create([
    'title' => 'Laravel Eloquent 入门',
    'content' => '这里是文章内容',
    'status' => 1,
]);

使用 create 时,需要在模型中配置 $fillable,否则可能无法批量写入。

也可以使用对象方式新增:

$post = new Post();
$post->title = 'Laravel Eloquent 入门';
$post->content = '这里是文章内容';
$post->status = 1;
$post->save();

对象方式更直观,适合需要逐步处理字段的场景。

六、更新数据

更新单条数据可以先查询,再修改:

$post = Post::findOrFail(1);
$post->title = '新的文章标题';
$post->save();

也可以使用批量更新:

Post::where('status', 0)->update([
    'status' => 1,
]);

批量更新适合后台批处理,但要注意条件范围,避免误改大量数据。

七、删除数据

删除单条数据:

$post = Post::findOrFail(1);
$post->delete();

按条件删除:

Post::where('status', 0)->delete();

如果项目需要保留删除记录,可以使用软删除。模型中引入 SoftDeletes

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;
}

同时需要在数据表中增加 deleted_at 字段:

$table->softDeletes();

软删除后,数据不会立刻从数据库中物理删除,而是记录删除时间。适合文章、订单、用户等需要恢复或审计的数据。

八、一对一关联

一对一关联适合两个表之间一条数据对应一条数据的关系。

例如,一个用户对应一个用户资料:

class User extends Model
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}

Profile 模型中可以写:

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

使用时:

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

九、一对多关联

一对多是项目中非常常见的关系。例如,一个分类下有多篇文章。

Category 模型中:

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

Post 模型中:

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

使用时:

$category = Category::find(1);
$posts = $category->posts;

或者查询文章所属分类:

$post = Post::find(1);
$category = $post->category;

十、多对多关联

多对多适合一个模型可以关联多个模型,另一个模型也可以反向关联多个模型的场景。

例如,一篇文章可以有多个标签,一个标签也可以属于多篇文章。

Post 模型中:

class Post extends Model
{
    public function tags()
    {
        return $this->belongsToMany(Tag::class);
    }
}

Tag 模型中:

class Tag extends Model
{
    public function posts()
    {
        return $this->belongsToMany(Post::class);
    }
}

Laravel 默认会使用中间表,例如 post_tag。如果中间表名称不同,可以在 belongsToMany 中指定。

return $this->belongsToMany(Tag::class, 'post_tag');

给文章绑定标签:

$post = Post::find(1);
$post->tags()->attach([1, 2, 3]);

同步标签:

$post->tags()->sync([2, 3, 4]);

sync 会让关联关系与传入数组保持一致,常用于后台编辑表单。

十一、避免 N+1 查询问题

使用模型关联时,要注意 N+1 查询问题。

例如:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->category->name;
}

如果有 100 篇文章,这种写法可能会额外查询 100 次分类。更好的方式是使用预加载:

$posts = Post::with('category')->get();

预加载可以减少数据库查询次数,提高列表页和接口性能。

多个关联也可以一起加载:

$posts = Post::with(['category', 'tags'])->get();

十二、Eloquent 使用注意事项

使用 Eloquent 时,建议注意以下几点:

  1. 查询列表时尽量使用分页,不要一次取出大量数据。
  2. 批量赋值时配置 $fillable,避免字段被意外写入。
  3. 关联查询时注意预加载,避免 N+1 查询。
  4. 大批量数据处理可以使用 chunk 分批读取。
  5. 复杂统计和性能敏感查询,可以结合查询构造器或原生 SQL。
  6. 不要把所有业务逻辑都堆进模型,复杂项目应合理拆分服务层。

Eloquent 写法简洁,但并不代表所有查询都要用模型强行完成。对于复杂报表、聚合统计和大数据量场景,仍然需要结合实际性能选择合适方案。

十三、常见问题

Eloquent 和 Query Builder 有什么区别?

Eloquent 是 ORM,围绕模型对象操作数据;Query Builder 更接近 SQL 构造器,适合灵活拼接查询。普通业务表适合用 Eloquent,复杂查询或性能敏感场景可以考虑 Query Builder。

Eloquent 模型必须和数据表同名吗?

不必须。Laravel 有默认命名规则,但可以通过 $table 指定模型对应的数据表。

为什么 create 方法写入失败?

常见原因是模型没有配置 $fillable,或者字段不在允许批量赋值范围内。也可能是数据库字段约束不允许为空。

Eloquent 适合大型项目吗?

适合,但要注意查询优化、关联预加载和业务分层。大型项目中通常不会把所有逻辑都写在模型里,而是结合服务层、仓储模式或查询对象管理复杂逻辑。

  • 广告合作

  • QQ群号:4114653

温馨提示:
1、本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。邮箱:2942802716#qq.com(#改为@)。 2、本站原创内容未经允许不得转裁,转载请注明出处“站长百科”和原文地址。
Laravel
上一篇: Laravel数据库迁移
Laravel
下一篇:

已经没有下一篇了!