美文网首页PHP开发
Laravel ORM Model 的预定义属性

Laravel ORM Model 的预定义属性

作者: patiencing | 来源:发表于2017-04-30 19:11 被阅读585次

缘起

后端开发的基本操作就是处理数据 -- "增删改查 / CURD", 而 Laravel 框架的"对象关系映射 (ORM = Object Relationship Mapping)" 为解决数据操作中的痛点和痒点提供了便捷的解决方案.


属性

$table 属性 -- 自定义关联的数据表

既然叫"对象关系映射", 则意味着有明确的对应关系和约定.

Laravel 约定数据表的表名是 Model 名的复数, 比如 User Model 对应的是 users 表, Order Model 对应的是 orders 表.
如果需要自定义, 可以通过覆写 $table 属性来指定表名:

protected $table = 'yourTableName';

$primaryKey 属性 -- 自定义主键

Laravel 约定每张表都有整型的 id 字段做为自增主键.

如果想设置其他字段做为主键,可以通过覆写 $primaryKey 属性来自定义.

protected $primaryKey = 'uid';

$timestamp 属性 -- 数据的时间戳属性

数据的可追溯性是非常重要的. 所以 Laravel 迁移文件默认带时间戳:

$table->timestamps();

所以通过迁移文件生成的数据表默认带 create_atupdated_at 字段, 在添加数据和更新数据时会分别自动更新这两个字段.

这两个字段是 MySQL 的 datetime 类型, 即这种样式: 2015-08-05 07:27:09.
但是个人觉得从 MySQL 检索优化的角度来说, int 型的 Unix 时间戳比 datetime 类型速度要快, 所以这样设置:

use Illuminate\Database\Eloquent\Model;

class PosterSubScribeModel extends Model
{
    protected $table = 'subscriber';
    protected $guarded = [''];

    /**
     * 获取当前Unix时间戳
     * @return int
     */
    public function freshTimestamp()
    {
        return time();
    }

    /**
     * 避免转换Unix时间戳为时间字符串
     *
     * @param \DateTime|int $value
     * @return \DateTime|int
     */
    public function fromDateTime($value)
    {
        return $value;
    }
}

PS. 如果不想使用 timestamp, 可以将其关闭:

protected $timestamps = FALSE;

$casts 属性 -- 转化数据类型

PHP 擅长处理数组, 而前后端交互通常用 JSON, 所以常见的场景是我们希望用"数组"处理数据和存储数据, 但是希望读取出来的是 JSON 格式.

这种场景下就可以使用 $casts 属性, 实现取出数据时自动转化为 JSON 数据:

namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    protected $casts = [
        'my_array_data' => 'json',
    ];
}

还有一种使用场景, 是把存储的 1 和 0, 在取出时自动转化为 true 和 false:

class User extends Model
{
    protected $casts = [
        'options' => 'json',
        'status' => 'bool',
    ];
}

**注意: **
$cast 并没有真的改变存储的数据类型,而是取出数据时暂时转换成设定的数据类型;


$attributes 属性 -- 默认值

给数据库里的一个字段设置默认值.

protected $attributes = [
    'goods_ids' => '[]', //可以配合 $casts, 取出数据时自动转化为 JSON
    'category_ids' => '[]',
    'display_order' => 0,
];

注意:
不能写成 'goods_ids' => []. 而必须给[]加上引号; 上次因为没有加引号, 存储数据时莫名出现多个空数据(暂时还未弄清楚原因).


$dates 属性 - 强大的时间类

时间数据经常面临"格式化"的问题, 比如"Unix时间戳"和"可读时间格式"的转化.

$date 属性可以解决这个问题.
设置成这个属性的时间数据可以自动转化为 Carbon 类的对象, 从而使用 Carbon 的方法来处理时间.

Carbon 类的方法很强大, 大家可以深入研究一下Carbon源码 或者是查看 Laravel 中的 Carbon 类 (/vendor/nesbot/carbon/src/Carbon/Carbon.php).
比如, 把"可读时间格式"(比如 2017-04-30 12:00) 转化为 "Unix 时间戳":

$model->deleted_at->timestamp

$guarded 和 $fillable 属性 -- 限制写入数据库的数据

因为 Eloquent 模型默认对批量赋值(Mass Assignment)进行保护. 这规则要求使用 create() 或者 update() 方法批量插入或者更新属性时, 需要先设置 $guarded$fillable 属性.

设置后, 在批量写入数据库时, 不光会筛掉数据表没有的字段, 也会筛选掉 $guarded$fillable 中限制的字段.

  • $guarded 是"黑名单", 写入这里的字段, 表示不可以被赋值; 如果所有字段都可以写入数据库, 可以这样写 protected $guarded = [''], 表示没有需要被 "guarded/保护" 的字段.
  • $fillable 是"白名单", 写入这里的字段, 表示只有在这些声明的字段可以被写入数据库;

注意:
一个 model 只能使用其中一个属性, 而不是一起使用.
一般来说, 因为这两个属性的适用场景是剔除非法赋值的数据, 所以$guarded 使用的频率高一些。


$hidden 和 $visible 属性 -- 设置数据的可见性

比如像 password 这种字段,是不希望在读取后呈现给用户看到的,那么可以把它隐藏:

  • 黑名单 $hidden 的写法
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    protected $hidden = ['password'];
}
  • 白名单 $visible 的写法
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    protected $visible = ['first_name', 'last_name']; //排除 password 字段
}

注意:

  • $guarded & $fillable 属性一样, 一个 model 只能使用 $hidden$visible 其中一个属性, 而不是同时使用.
    一般来说, 由于这两个属性的适用场景是"隐藏数据", 所以 $hidden 使用的频率高一些。
  • 对于"关联查询"
    • 如果要隐藏整张关联表的字段,需要在 $hidden 中填写"表间关系的方法"(比如 hasManyPost)
    • 如果要隐藏关联表里的部分字段,则需要到关联表的 model 里去设置 $hidden / $visible 属性.

$appends 属性 -- 添加属性

开发 API 接口时, 前端经常会要求提供一些数据表没有的字段, 这时候, 就需要使用 $appends 属性了. 在查询数据库返回的数据中, 手动增加新的数据:

namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
    public function getIsAdminAttribute()
    {
         return 'yes';
    }
     protected $appends = ['is_admin'];
}

这时, 查询 users 表的数据时, 就多了一个 is_admin 的数据.


$deleted_at 属性 -- 软删除

数据是宝贵的, 而硬盘存储的成本非常低廉, 所以删除数据时一般只是添加删除标识而并不真的删除数据.

Laravel 提供了"软删除"方案, 使用 deleted_at 字段保存数据的删除时间. 查询数据时, 被软删除的数据将会自动从查询结果中排除.

想要使用"软删除", 需要这样设置:

  • 1.创建数据表时在"迁移文件"中加入 deleted_at 字段:
public function up()
{
    Schema::table('flights', function ($table) {
        $table->softDeletes();
    });
}

或者是创建迁移文件在已有的数据表中添加 deleted_at 字段:

public function up()
{
    Schema::table('poster', function (Blueprint $table) {
        $table->integer('deleted_at')->nullable()->comment('删除时间');
    });
}

public function down()
{
    Schema::table('poster', function (Blueprint $table) {
        $table->dropColumn('deleted_at');
    });
}
  • 2.引入 SoftDeletes 的 trait, 并声明 deleted_at 字段是 $dates 属性:
namespace App;

use app\common\models\BaseModel;
use Illuminate\Database\Eloquent\SoftDeletes;

class Poster extends BaseModel
{
    use SoftDeletes;

    protected $dates = ['deleted_at'];
}

如果想要查询出这些被删除的数据时, 只要加上 withTrashed() 方法即可.


参考文章


文章历史

  • 2017/04/30 (第一次发布)
  • 2017/05/03 润色
  • 2017/06/03 润色
  • 2017/06/14 润色

如果我的文章对你有用, 希望给些改进的建议, 或者打个"喜欢" _

相关文章

网友评论

    本文标题:Laravel ORM Model 的预定义属性

    本文链接:https://www.haomeiwen.com/subject/jwpxtxtx.html