数据库操作:Eloquent ORM详解
在本章中,我们将详细介绍Laravel的Eloquent ORM,讲解如何定义模型、执行数据库查询、以及建立模型之间的关系。通过学习本章,你将能够高效地与数据库进行交互。
1. Eloquent ORM简介
Eloquent ORM(对象关系映射)是Laravel自带的ORM,用于简化数据库操作。Eloquent允许你使用模型类与数据库表进行交互,每个模型类通常对应一个数据库表。
1.1 创建模型
你可以使用 artisan
命令创建一个模型:
php artisan make:model Post
上述命令将在 app/Models
目录下创建一个名为 Post.php
的模型文件。你也可以使用 -m
选项同时创建模型和迁移文件:
php artisan make:model Post -m
1.2 定义模型
模型类通常继承自 Illuminate\Database\Eloquent\Model
。以下是一个基本的模型类:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
// 模型代码
}
Eloquent将默认使用复数形式的类名作为数据库表名,例如,Post
模型将使用 posts
表。如果你的表名不同,可以在模型中指定:
class Post extends Model
{
protected $table = 'my_posts';
}
2. 数据库迁移
数据库迁移是定义数据库结构的方式,它们是可版本控制的文件。让我们来创建和应用一个简单的迁移。
2.1 创建迁移
如果你在创建模型时使用了 -m
选项,迁移文件会自动生成。你也可以单独生成迁移文件:
php artisan make:migration create_posts_table
迁移文件将存储在 database/migrations
目录下。
2.2 定义迁移
打开迁移文件 create_posts_table
,添加以下代码:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
up
方法定义了迁移中要执行的操作,而 down
方法定义了回滚迁移时要执行的操作。
2.3 运行迁移
运行以下命令来执行迁移:
php artisan migrate
此命令将创建 posts
表。
3. Eloquent 模型基础操作
Eloquent 提供了一些基本的数据库操作方法,如创建、读取、更新和删除(CRUD)。
3.1 创建数据
你可以使用模型的 create
方法来插入数据。确保在模型中定义 fillable
属性,以防止批量赋值漏洞:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'content'];
}
然后,你可以使用以下代码创建一条记录:
use App\Models\Post;
$post = Post::create([
'title' => 'First Post',
'content' => 'This is the content of the first post.',
]);
3.2 读取数据
你可以使用模型的 all
方法读取所有数据,或使用 find
方法按主键查找数据:
$posts = Post::all();
$post = Post::find(1);
你还可以使用查询构建器方法:
$posts = Post::where('title', 'First Post')->get();
3.3 更新数据
你可以使用模型实例的 save
方法来更新数据:
$post = Post::find(1);
$post->title = 'Updated Post Title';
$post->save();
或者使用 update
方法:
Post::where('id', 1)->update(['title' => 'Updated Post Title']);
3.4 删除数据
你可以使用模型实例的 delete
方法来删除数据:
$post = Post::find(1);
$post->delete();
或者使用 destroy
方法按主键删除数据:
Post::destroy(1);
4. 模型关系
Eloquent 提供了多种类型的模型关系,包括一对一、一对多和多对多关系。
4.1 一对一关系
一对一关系是指一个模型对应另一个模型。例如,一个用户有一个手机号码。
创建相关模型:
php artisan make:model User -m
php artisan make:model Phone -m
定义迁移:
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
class CreatePhonesTable extends Migration
{
public function up()
{
Schema::create('phones', function (Blueprint $table) {
$table->id();
$table->string('phone_number');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('phones');
}
}
运行迁移:
php artisan migrate
在 User
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function phone()
{
return $this->hasOne(Phone::class);
}
}
在 Phone
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Phone extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
使用关系:
$user = User::find(1);
$phone = $user->phone;
$phone = Phone::find(1);
$user = $phone->user;
4.2 一对多关系
一对多关系是指一个模型对应多个模型。例如,一个博客文章有多个评论。
创建相关模型:
php artisan make:model Post -m
php artisan make:model Comment -m
定义迁移:
class CreatePostsTable extends Migration
{
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('posts');
}
}
class CreateCommentsTable extends Migration
{
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('comments');
}
}
运行迁移:
php artisan migrate
在 Post
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
在 Comment
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
public function post()
{
return $this->belongsTo(Post::class);
}
}
使用关系:
$post = Post::find(1);
$comments = $post->comments;
$comment = Comment::find(1);
$post = $comment->post;
4.3 多对多关系
多对多关系是指多个模型对应另一个多个模型。例如,一个学生可以参加多个课程,一个课程可以有多个学生。
创建相关模型:
php artisan make:model Student -m
php artisan make:model Course -m
php artisan make:migration create_course_student_table --create=course_student
定义迁移:
class CreateStudentsTable extends Migration
{
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('students');
}
}
class CreateCoursesTable extends Migration
{
public function up()
{
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('courses');
}
}
class CreateCourseStudentTable extends Migration
{
public function up()
{
Schema::create('course_student', function (Blueprint $table) {
$table->id();
$table->foreignId('student_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('course_student');
}
}
运行迁移:
php artisan migrate
在 Student
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
public function courses()
{
return $this->belongsToMany(Course::class);
}
}
在 Course
模型中定义关系:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Course extends Model
{
public function students()
{
return $this->belongsToMany(Student::class);
}
}
使用关系:
$student = Student::find(1);
$courses = $student->courses;
$course = Course::find(1);
$students = $course->students;
5. Eloquent事件
Eloquent 提供了模型事件,你可以在模型的生命周期中执行一些操作。例如,当模型被创建、更新或删除时触发相应的事件。
5.1 定义事件
你可以在模型中定义事件,例如 creating
、created
、updating
、updated
、deleting
和 deleted
:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected static function booted()
{
static::creating(function ($post) {
// 在模型创建之前执行的操作
});
static::created(function ($post) {
// 在模型创建之后执行的操作
});
}
}
5.2 使用事件类
你也可以使用事件类来组织你的事件处理逻辑:
namespace App\Providers;
use App\Models\Post;
use App\Observers\PostObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Post::observe(PostObserver::class);
}
}
在 app/Observers
目录下创建一个观察者类:
namespace App\Observers;
use App\Models\Post;
class PostObserver
{
public function creating(Post $post)
{
// 在模型创建之前执行的操作
}
public function created(Post $post)
{
// 在模型创建之后执行的操作
}
}
6. Eloquent作用域
作用域是一种将常用的查询逻辑封装在模型中的方式,使得代码更具可读性和重用性。
6.1 本地作用域
本地作用域使用模型的方法定义。以下是一个示例:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function scopePopular($query)
{
return $query->where('views', '>', 100);
}
}
你可以使用本地作用域来查询数据:
$popularPosts = Post::popular()->get();
6.2 全局作用域
全局作用域应用于模型的所有查询。以下是一个示例:
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class ActiveScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->where('status', 'active');
}
}
在模型中应用全局作用域:
namespace App\Models;
use App\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected static function booted()
{
static::addGlobalScope(new ActiveScope);
}
}
你可以使用 withoutGlobalScope
方法临时禁用全局作用域:
$users = User::withoutGlobalScope(ActiveScope::class)->get();
7. 序列化
Eloquent 模型可以轻松地转换为数组或JSON,这在构建API时非常有用。
7.1 转换为数组
你可以使用 toArray
方法将模型转换为数组:
$post = Post::find(1);
$array = $post->toArray();
7.2 转换为JSON
你可以使用 toJson
方法将模型转换为JSON:
$post = Post::find(1);
$json = $post->toJson();
也可以直接返回模型实例来自动转换为JSON:
return Post::find(1);
总结
在本章中,我们详细介绍了Laravel的Eloquent ORM,包括模型定义、数据库迁移、基本CRUD操作、模型关系、事件、作用域和序列化。通过这些知识,你可以高效地与数据库进行交互,并构建复杂的数据模型。在接下来的章节中,我们将探讨Laravel的中间件和用户认证。
希望这篇文章能帮助你更好地理解Laravel的Eloquent ORM,欢迎继续关注后续的教学文章!