模型

概述

要使用模型需要先修改 usr/init.php,取消 \Cabal\DB\Model::setDBManager($server->db()); 注释。

这里顺便说一下,Martin Fowler架构大神 很久之前就开始质疑ORM到底好与不好了[点击查看原文]。

使用 ORM 后通常开发效率会提高很多,但是在复杂的业务场景下,对象到处传递后,对象的值和数据库中的值是否一致变得很模糊,也就会增加代码的复杂度和维护难度变高。

定义

下面是一个最简单的 模型类:

  1. use Cabal\DB\Model;
  2. class User extends Model
  3. {
  4. // 表名
  5. protected $tableName = 'user';
  6. }

模型类还支持下面的配置和语法:

  1. use Cabal\DB\Model;
  2. use Cabal\DB\Table;
  3. class User extends Model
  4. {
  5. // 表名
  6. protected $tableName = 'user';
  7. // 日期字段 这些字段会字段转换为 Carbon\Carbon 对象
  8. protected $dates = array('created_at', 'deleted_at', 'updated_at');
  9. // 是否使用数据时间戳 - created_at&updated_at 字段会自动填充创建时间也编辑时间
  10. protected $timestamps = true;
  11. // toArray 时会追加的字段 需要定义 __getXX魔术方法
  12. protected $appends = ['anno_name'];
  13. // 允许用 fill 方法填充的字段
  14. protected $fillable = array();
  15. // 不允许自动填充的字段
  16. protected $guarded = array('*');
  17. // 日期字段 数据库保存格式
  18. protected $dateFormat = 'Y-m-d H:i:s';
  19. // 数据库不存在的字段 可以使用魔术方法支持获取
  20. public function __getAnnoName($value = null)
  21. {
  22. return 'AnnoName';
  23. }
  24. // 复杂的数据格式可以用一对魔术方法实现 写入序列话,读取反序列化
  25. public function __getJson($value = null)
  26. {
  27. return json_decode($value, true);
  28. }
  29. public function __setJson($value)
  30. {
  31. $this->dbData['json'] = json_encode($value);
  32. }
  33. // 可以自定义关联数据字段
  34. public function __getPublishArticles()
  35. {
  36. return $this->has(Article::class, function (Table $table) {
  37. $table->where('status = ?', 1);
  38. }, 'publishedArticle');
  39. }
  40. }

增删改查

查询

查询语法和 DB 基础语法一致,只是需要用 ModelName::query() 开始一个查询。

  1. User::query()->where('id = ?', 1)->first();
  2. User::query()->rows();
  3. User::query()->paginate(3, 2);

创建

一个新的模型对象调用 ->save() 方法表示创建。

  1. $user = new User;
  2. $user->name = uniqid();
  3. $user->save();

编辑

一个已存在的模型对象 调用 ->save() 方法只会保存修改过的字段,如果没用修改过的字段不会操作数据。

  1. $user = User::query()->first();
  2. $user->name = 'new name';
  3. $user->save();

删除

  1. $user = User::query()->first();
  2. $user->delete();

魔术方法

采用的是和PHP的模式方法类似的 __ 开头函数,方法名采用驼峰命名,如字段 ->anno_name 对应的是 __getAnnoName 方法。

可以采用一对魔术方法实现数据库字段自动序列化和反序列化:

  1. public function __getJson($value = null)
  2. {
  3. return json_decode($value, true);
  4. }
  5. public function __setJson($value)
  6. {
  7. $this->dbData['json'] = json_encode($value);
  8. }

关联查询

模型的关联查询和关联查询的语法类似,只是第一个参数从表明变成了类名:

$user->has($model, $foreignKeyOrCallback = null, $callback = null, $storeKey = null);

  • className 目标类名
  • foreignKeyOrCallback 外键名称或者回调函数,如果不传或传入的是一个函数则外键默认为:表名+_id user_id
  • callback 回调函数,可以自己追加一些查询条件
  • storeKey 存储键名 默认为类名,同一个关联类多次查询但是条件不同需要自定义存储键名

$article->belongs($model, $foreignKeyOrCallback = null, $callback = null, $storeKey = null);

  • className 目标类名
  • foreignKeyOrCallback 外键名称或者回调函数,如果不传或传入的是一个函数则外键默认为:目标表表名+_id user_id
  • callback 回调函数,可以自己追加一些查询条件
  • storeKey 存储键名 默认为类名,同一个关联类多次查询但是条件不同需要自定义存储键名
  1. use Cabal\DB\Table;
  2. $articles = $user->has(Article::class, function (Table $table) {
  3. $table->where('status = ?', 1);
  4. }, 'publishedArticle');