laravel Eloquent ORM

Eloquent 是 Laravel 中对 Active Recode pattern (领域模式) 的实现。它通过 「模型」的概念来根数据表进行交互。

ORM, Active Record and Eloquent
ORM - Object/Relational Mapping (对象/关系映射),是随着面向对象的软件开发方法发展而产生的一种技术,用来把对象模型表示的对象映射到基于 SQL 的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作实体对象的属性和方法。ORM 技术是在对象和关系之间提供了一条桥梁,前台的对象型数据和数据库中的关系型的数据通过这个桥梁来相互转化。
Active Record ,是一种领域模型模式,特点是一个「模型」类对应关系型数据库中的一个表,而「模型」类的一个实例对应表中的一行记录。
流行的Web开发框架,如 CodeIgniter ,Ruby on Rails 和 Symfony 都使用Active Record 模式来简化数据库操作。 而 Eloquent 就是 Laravel 自己的 Active Record 模式的实现。

Eloquent 是 Laravel 提供的 ORM 实现。它将数据库抽象为对象,这些对象 (也称为「模型」) 被创建、更新或删除时,Eloquent 会在数据库中进行相应的更改。

下图显示了一个 Eloquent 的简单示例,通过创建一个新的 PHP 对象并为其属性分配值,在表 users 中插入一行:

laravel Eloquent ORM

Eloquent 通过创建数据之间的关系,简化了复杂数据库结构的工作。它内置了各种关联关系:

  • 将记录从一个表链接到另一个表的另一个记录(一对一关联)
  • 将记录从一个表链接到不同表中的多个记录(一对多关联)
  • 将一个表中的一些记录链接到另一个表中的记录数(多对多关联)
  • 一个表的记录可以动态链接到许多其他表(多态关联)
  • 更多

数据库中数据实体之间的这些内置关系帮助开发人员轻松的处理数据。 例如,下图显示了一个博客程序中用户、贴子、评论的数据实体之间关系:

laravel Eloquent ORM

Model - 模型

像其他 ORM 实现一样,Eloquent 的「模型」是一个特殊的类,它表示数据库中的单个表。 使用「模型」可以以对象的方式来处理数据库中的数据。

当这些类 (模型) 使用 Eloquent 的功能时,Laravel 会自动进行数据库的 SQL 查询并返回结果:

laravel Eloquent ORM

将「模型」视为应用程序使用的对象或实体。 例如,如果应用程序是一个在线商店,那么它所使用的对象就是产品,订单,产品类别,用户等。如果应用程序是 SNS - 对象将是状态,照片,视频, 位置,用户之间的关系等。以这种方式表示实体可以大大简化数据库的结构,并使您能够在应用程序中使用 Eloquent。

定义模型时的约定

通过 Eloquent 的模型处理数据库表时,Laravel 主要有三个主要假设:

  • 表的主键是一个名为 id 的无符号自动递增整型。
  • 该表具有 datetime 类型的 created_at 和 updated_at 字段以存储创建时间、更新时间的时间戳。
  • 如果模型类为 User.php ,则表名应该称为 users,即以模型类的蛇形、复数形式名称来作为数据表的名称

定义模型名的时候,最好不要使用 Laravel 中已经用到的一些类名,例如:App, Auth, Cache, Config, Controller, Cookie, Crypt, Lang, Route, Event, Log, Schema, File, Mail, Session, Form, Password, View, Hash, Queue, Input, Request 等。

创建并使用 Eloquent

每个模型类对应了数据库中的一个表,例如有一个博客程序中的贴子表:

laravel Eloquent ORM

我们这样定义它:

// app/Post.php
namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model {}

接下来就可以通过它来进行数据库的增、删、改、查各种操作了。

使用模型

Eloquent 提供了许多方法来操作数据库。 基本的方法如下:

  • all() - 取回所有记录
  • find($id) - 取回一条记录
  • first() - 取回第一条记录
  • save() - 将当前模型实例作为新记录添加到数据库中
  • create($data) - 通过数据数组创建一条新记录
  • delete() - 删除当前记录
  • destroy($id) - 删除主键值为 $id 的记录

与 Query Builder 一样,Eloquent 的大部分方法可以进行链式操作。它们还可以与 Query Builder 交替使用。

假设我们有下面两个表:

laravel Eloquent ORM

Eloquent 模型的属性表示模型对应的表的列,模型的属性表示列的值。例如,如果您想从 posts 表中检索 ID 为 1 的标题和内容,您可以访问 Post 模型的 title 和 body 属性,如下面的图所示:

laravel Eloquent ORM

例如:

try
    Route::get('posts/new', function(){
    // Create a new instance of the Post model
    $post = new App\Post;
    // Assign values to model’s attributes
    $post->title = "My first post";
    // Assign values to model’s attributes
    $post->body = "This post is created with Eloquent";
    // Insert the record in the DB
    $post->save();
    // Display the new record containing the blog post
    return $post;
});

Laravel 背后的执行过程如下:

laravel Eloquent ORM

 

这时就可以发现 Eloquent 与 Query Builder 的区别了:

  • 通过模型不需要指定记录将插入哪个表。
  • 通过使用对象而不是运行任何数据库操作来完成新记录的创建。

常用示例:

#使用 Query Builder 的 find() 取回单条记录
$comment = Comment::find(2);
#相当于
Comment::where('id',$id)->get();


#使用 Eloquent 的 first() 取回单条记录
 Route::get('comments/first', function() {
    $comment = Comment::where('body', 'like', '%comment%')->first(); 
});


#使用 all() 取回所有记录
Route::get('comments', function() {
    $comments = Comment::all();
});


#使用 get() 取回多条记录
Route::get('comments', function() {
    $comments = Comment::get();
});

Route::get('posts', function() {
    $posts = Post::where('title', 'like', '%Laravel%')->get();
});

Route::get('posts', function() {
    $posts = Post::get(['title','body']);
});


#Updating records - 更新记录
#1、通过在模型上使用 find(), get() 或 first() 来检索属于模型的记录
#2、为模型的属性分配新值
#3、在模型上调用 save() 来保存数据库中的更改
Route::get('posts/update', function() {
    $post = Post::find(1);
    $post->title = "Updated title"; 
    $post->save();
});
#注意:Eloquent 不允许一次性更新多条记录,如有需要可以使用 Query Builder 的 update() 方法。

#Deleting records - 删除记录
Route::get('posts/delete', function() {
    $post = Post::find(1);
    $post->delete();
});

Route::get('posts/destory', function() {
    $post = Post::destory(1);
});

参考:https://laravel-china.org/articles/6356/laravel-eloquent-usage