使用Eloquent ORM可以非常方便的与数据库打交道,每张数据表都对应一个与该表进行交互的模型(Model),通过模型类,我们可以对数据表进行查询、插入、更新、删除等操作。

在阅读本文之前,请先查阅本站文章《使用illuminate database查询构造器进行数据库操作》中有关数据库的连接配置。本文以Slim框架为例,讲解在MVC框架中Eloquent ORM的使用,在其他框架中如Laravel使用是一致的。

定义模型

我们从创建一个 Eloquent 模型开始,模型类通常位于 appmodel目录下,你也可以将其放在其他可以被composer.json 文件自动加载到的地方。所有 Eloquent 模型都继承自IlluminateDatabaseEloquentModel类。

我们来看一个Article模型的例子,我们将用该类获取和存取数据表Article(文章)中的信息:

<?php 
namespace AppModels;

use IlluminateDatabaseEloquentModel;

class Article extends Model
{
    protected $table = 'article';
    
    // public $timestamps = false;
    // const CREATED_AT = 'creation_date';
    // const UPDATED_AT = 'last_update';
    
    // 允许可被赋值的字段
    // protected $fillable = ['title', 'author'];
    // 不可被赋值的字段
    // protected $guarded = ['price'];
}

代码中,使用protected $table = 'article';定义了模型所使用的数据表是article,默认情况下,Eloquent每张表的主键名为id,数据表中应该有时间戳created_atupdated_at两个字段,表示数据的创建时间和更新时间,我们在插入和更新模型的时候,Eloquent会自动为这两个字段更新值。如果你的数据表中没有这两个字段或者是被其他字段名替代这两个字段,则需要在模型中设置CREATED_ATUPDATED_AT常量。如果你不想使用默认的时间戳,也可以使用public $timestamps = false;来关闭时间戳。

如果我们在插入或更新模型数据时,只允许更新某个字段,其他非法提交的字段不允许更新,则可以使用来protected $fillable = ['title', 'author'];约束字段的操作,'title', 'author'是article表中的两个字段。同样的如果不允许更新某个字段,可以使用protected $guarded = ['price'];来限制更新。

获取模型

创建完模型及其关联的数据表后,就可以从数据库中获取数据了。将 Eloquent 模型看作功能强大的查询构建器,你可以使用它来流畅的查询与其关联的数据表。例如:

<?php
use AppModelsArticle;

$articles = Article::all();

foreach ($articles as $article) {
    echo $article->title;
}

Eloquent 的all方法返回模型表的所有结果,由于每一个 Eloquent 模型都是一个查询构建器,你还可以添加约束条件到查询,然后使用get 方法获取对应结果:

$articles = Article::where('cid', 1)
               ->orderBy('id', 'desc')
               ->take(10)
               ->get();

其实本质上 Eloquent 模型就是查询构建器,你可以在 Eloquent 查询中使用查询构建器的所有方法。

获取单个模型

我们可以使用findfirst 获取单个记录。这些方法返回单个模型实例而不是模型集合:

// 通过主键获取模型...
$article = Article::find(1);

// 获取匹配查询条件的第一个模型...
$article = Article::where('cid', 1)->first();

还可以通过传递主键数组来调用find方法,这将会返回匹配记录集合:

$article = Article::find([1, 2, 3]);
获取聚合结果

当然,我们还可以使用查询构建器提供的聚合方法,例如 countsummax,以及其它查询构建器提供的聚合函数。这些方法返回计算后的结果而不是整个模型实例:

$count = Article::where('cid', 1)->count();
$max = Article::where('cid', 1)->max('hits');

插入模型

我们想要在数据库article表中插入新的记录,只需创建一个新的模型实例,设置模型的属性,然后调用save方法:

<?php 
namespace AppControllers;

use SlimHttpRequest;
use SlimHttpResponse;
use AppModelsArticle;

class ArticleController extends Controller
{
    /**
     * 创建一个新的文章实例
     *
     * @param  Request  $request
     * @return Response
     */
    public function create($request, $response)
    {
        // 验证请求...

        $article = new Article;

        $article->title = $request->title;

        $article->save();
    }
}

在这个代码中,我们只是简单分配 HTTP 请求中的title参数值给 AppModelsArticle模型实例的title属性,当我们调用save方法时,一条记录将会被插入数据库。created_atupdated_at时间戳在save方法被调用时会自动被设置,所以没必要手动设置它们。

更新模型

save方法还可以用于更新数据库中已存在的模型。要更新一个模型,应该先获取它,设置我们想要更新的属性,然后调用save方法。同样,更新模型时,updated_at时间戳会被自动更新,所以没必要手动设置其值:

$article = Article::find(1);
$article->title = '新文章标题';
$article->save();
批量更新

我们还可以同时修改给定查询提供的多个模型实例,在本例中,所有类型为1且 author=Somebody的文章都被标记为hot(热门文章):

Article::where('cid', 1)
      ->where('author', 'Somebody')
      ->update(['hot' => 1]);

update方法要求以数组形式传递键值对参数,代表着数据表中应该被更新的列。

不存在则创建

插入数据前,先要判断是否已存在,如果数据已存在则不需要再重复插入,如果数据不存在才插入,这种场景可以使用firstOrCreate/firstOrNew完美解决。

$article = Article::firstOrCreate(['title' => 'test']);
        $article = $test->save();
不存在则创建,存在则更新

如果模型已存在则更新,否则创建新模型,可使用updateOrCreate来处理这种场景。例:如果有title=tet和cid=1的记录,则更新,否则创建新的记录。

Article::updateOrCreate(
     ['title' => 'test', 'cid' => 1],
     ['title' => 'helloweba']
);

删除模型

我们要删除一个模型,调用模型实例上的delete方法:

$article = Article::find(1);
$article->delete();

上面的例子中,我们在调用delete 方法之前从数据库中获取该模型,不过,如果我们知道模型的主键的话,可以调用destroy方法直接删除而不需要获取它:

Article::destroy(1);
Article::destroy([1, 2, 3]);
Article::destroy(1, 2, 3);

还可以通过查询删除多个模型:

$deletedRows = Article::where('active', 0)->delete();

小结

本文简要讲述了Eloquent模型的使用方法,在实际项目应用中能方便快捷的通过模型操作数据库,大大提高编码效率。