Laravel 的 Eloquent模型 中的属性访问控制意义及实践

咱们在定义一个本身的 Laravel 模型时都须要继承 Illuminate\Database\Eloquent\Model 这个类,在这个类中定义了不少模型相关的操做和行为。今天咱们来重点说说 Model 中包含的属性。数据库

在框架定义属性中访问权限通常有 protectedpublic 两种,这两种属性是在咱们继承基础模型后能够重写的,那为何不统一都是protected,是由于有一些属性咱们须要去动态改变。框架

protected 的属性咱们通常只重写一次或者使用基类提供的默认值,例如:学习

protected $table
protected $primaryKey = 'id';
protected $keyType = 'int';复制代码

以上这些都是只须要在继承基类的时候重写就能够了,分别表示模型的对应的表名、主键字段名、主键类型。spa

在软件的生命周期内这些属性都不须要再出改变。code

而有几个特殊的属性使用的 public 权限:继承

public $incrementing = true;
public $exists = false;
public $wasRecentlyCreated = false;
public static $snakeAttributes = true;
public static $manyMethods = [
        'belongsToMany', 'morphToMany', 'morphedByMany',
        'guessBelongsToManyRelation', 'findFirstMethodThatIsntRelation',
    ];
public $timestamps = true;复制代码

这些属性有些在 Illuminate\Database\Eloquent\Model 有些在 Model 使用的 trait 中。生命周期

如今咱们就拿 $exists$timestamps 这两个来举例说明为何框架会将他们的访问属性定义为 public资源

$exists

这个属性用来指示模型中数据是否存在,典型的判断在 model 的 save() 方法中,若是 $exists = true 那么 save() 执行的就是数据库的 update 操做,若是是 false 执行的就是 instert 操做。rem

好比你有一个这样的场景,这个模型在作正常的存储的时候都是执行正常的 save 逻辑,而在特殊的时候须要所有操做都是 inster 操做就能够在调用 save 前将此属性手动赋值为 true。get

这样的场景有典型应用就是用户。

public function register(Request $rquest) {

    $model = new User();

    $model->exists = false;

    $model->create($request->only('email', 'name', 'password'))

    $model->save()

}

public function updateName(Request $rquest) {

    $model = User::find($id, $request->get('id'));

    $model->exists = true;

    $model->name = $request->get('name')

    $model->save()

}复制代码

以上是一个伪代码的用户注册和用户更新字段方法,咱们手动去将$exists属性修改成咱们操做想要其达到效果以保证其每次执行都是咱们想要的效果而非产生咱们不想要的反作用。

固然这个例子可能不是一个最佳实践,由于这些判断框架内部都帮咱们坐在,这个属性最大做用仍是用于判断,好比你调用了一些模型操做,想要查看一看一下这个属性的bool值,以帮助你作下一步的判断,以执行不一样的逻辑时更有做用。

$timestamps

这个属性是我将要着重说的属性,由于我认为它在个人代码中目前找到了最佳实践。

我如今有一个表,是文章表,我在文章表里冗余了须要文章的属性,好比阅读数,关注数,评论数,收藏数,就是为了减小获取这篇文章的时候那些关联查询,以使得文章的首次加载速度更快。对我来讲此时获取一个关注的数去查询一次文章关注表是不划算的。

可是我在获取文章的是又要将阅读数自增,以反映有人点开并阅读了此文章一次。可是鉴于Laravel默认会自动管理个人文章模型 created_atupdated_at 这个两个字段,我每次更改阅读数,模型同时会更新记录的 updated_at 到最新时间,这并非我想要的结果。

因而我将 $timestamps 在模型定义为 false , 这样个人时间就不会被框架自动管理。

可是这样作又产生一个问题,虽然我不想我在更改阅读数,关注数这些冗余数据是让框架自动管理个人记录时间,可是我却想在建立和文章编辑提交时更新时间。

固然方法有,我能够手动传递当前时间给模型,也是能够实现的。可是毕竟这样不够优雅,且原本框架提供的功能我却要本身再去实现它,让我以为这是一种资源浪费,并且手动维护这些时间是繁琐易出错的。

当我看到这个访问控制的 public 的时候,我以为我能够同时实现个人这两个需求,并且不须要本身手动传递时间。

/** * 查看文章 */
public function showArticle($id) {
    $article = Article::find($id);

    $article->timestamps = false; // 模型已经定义,可省略

    $article->increment('views');

    $article->save();

    return $article;
}

/** * 建立文章 */
public function createArticle(Request $request) {
    $article = Article::crete($request->all());

    $article->timestamps = true;

    $article->save();

    return $article;
}

/** * 更新文章 */
public function updateArticle($id, Request $request) {
    $article = Article::find(id);

    $article->timestamps = true;

    $article->update($request->all());

    return $article;
}复制代码

这样我就不用手动传递时间给模型了,模型会用自身的功能帮我维护记录的时间。

总结

这些 public 的属性就是方便外部能够访问它们或者能够根据本身场景来动态的改变它们,以符合你的指望,这些属性我并无彻底研究清楚他们的最佳实践,这篇文章算是抛砖迎玉,但愿你们也能为我提供大家的最佳实践以供咱们互相学习。

相关文章
相关标签/搜索