Active Record 模型是一种设计模式,用面向对象的方式抽象地访问数据的模式。在 Yii2 中,每一个 Active Record 模型对象的实例是 yii\db\ActiveRecord 类或它的子类,它封装了数据库表或视图中的一行记录,并封装了所有逻辑和访问数据库的细节,如果有大部分的业务逻辑,很适合使用这种模式。

1. ActiveRecord 模型概述

       在大多数企业级开发中,都需要用到面向对象方法和关系型数据库。在软件的业务逻辑层和用户界面层,都需要操作对象,而在操作对象后,需要把对象的信息存储至数据库中。因此,在 MVC 模式下开放一个应用程序时,程序员要写很多数据访问层的代码,用来执行增删改查。通常情况下,这些数据访问层的代码基本上都是先传入操作对象,然后设置存储过程,再设置对象与属性对应,最后执行存储过程。这些具有相同模式的代码,在每个软件项目都重复出现,这显然是一种资源的浪费,由此,可以使用 ActiveRecord 模型解决这些问题。

       ActiveRecord (AR)模型是一种流行的对象——关系映射技术。对象——关系映射(Object Relational Mapping,ORM)是一种为解决面向对象与关系型数据库存在的互不匹配现象的技术。ORM 在关系型数据库和对象之间产生一个自动映射,这样在具体的数据库操作中就不需要再与复杂的 SQL 语句打交道。软件设计人员只需要关注业务逻辑中的对象架构,而不是底层重复性的数据库 SQL 语句。

下面是一个 user 表的模型类

<?php
namespace common\models; use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface; /**
* User model
*
* @property integer $id
* @property string $username
* @property string $password_hash
* @property string $password_reset_token
* @property string $email
* @property string $auth_key
* @property integer $status
* @property integer $created_at
* @property integer $updated_at
* @property string $password write-only password
*/
class User extends ActiveRecord implements IdentityInterface
{ /**
* {@inheritdoc}
*/
public static function tableName()
{
return '{{%user}}';
} /**
* {@inheritdoc}
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
} /**
* {@inheritdoc}
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
} }

演示下 AR 的新增操作吧

$user = new User(); // 实例化 user 表对应的 ActiveRecord 模型类
$user->username = '小牛'; // 给表中的 username 字段赋值
$user->email = '18810980488@163.com'; // 给表中的 email 字段赋值
$user->save(); // 执行 insert into 语句完成一次插入记录的操作

上面的代码相当于执行了下面的 SQL 语句。

insert into user('username','email') value('小牛','18810980499@163.com');

ActiveRecord 的优点是简单、直观,一个类就包括了数据访问和业务逻辑。减少了软件开发时间和成本,极大的提高了数据的可读性,也简化了代码的调优和测试。

2. 通过查询操作理解 ActiveRecord 类

静态方法 find() 返回了 ActiveRecord 类的静态实例对象,从而可以调用其他的方法,查询实例。

我们打印了一个 one() 方法查询返回的信息,如下:

api\models\UserRole Object
(
[_attributes:yii\db\BaseActiveRecord:private] => Array
(
[role_id] => 1
[role_name] => 超级管理员
[role_desc] => 超级管理员
[role_sort] => 10
[created_at] => 2019-06-17 15:10:21
[delete_flg] => 0
[updated_uid] => 1
[updated_at] => 2019-06-19 18:12:40
) [_oldAttributes:yii\db\BaseActiveRecord:private] => Array
(
[role_id] => 1
[role_name] => 超级管理员
[role_desc] => 超级管理员
[role_sort] => 10
[created_at] => 2019-06-17 15:10:21
[delete_flg] => 0
[updated_uid] => 1
[updated_at] => 2019-06-19 18:12:40
) [_related:yii\db\BaseActiveRecord:private] => Array
(
) [_relationsDependencies:yii\db\BaseActiveRecord:private] => Array
(
) [_errors:yii\base\Model:private] =>
[_validators:yii\base\Model:private] =>
[_scenario:yii\base\Model:private] => default
[_events:yii\base\Component:private] => Array
(
) [_eventWildcards:yii\base\Component:private] => Array
(
) [_behaviors:yii\base\Component:private] => Array
(
) )

one()方法找到了一个满足查询条件的行,返回一个实例对象,实例的属性含有数据表行中相应列的值。然后,就可以像读取普通对象的属性那样读取查询结构

$role->role_name; // 输出 “超级管理员”

如果是传统的面向对象语言,如 C++ 或 Java,这里就会报编译错误,因为类没有定义“role_name”成员属性。而对于 PHP 而言,语言有着对动态特性(魔术方法)的支持,当写入【读取】对象属性不存在时,会触发 ActiveRecord 中定义的 __set()【__get()】 方法,这样的调用就没有任何问题。

3. 通过插入和更新操作理解 ActiveRecord 类

同样使用 save() 方法执行插入和更新操作。如果实例对象是 new 操作符创建的,调用 save() 方法会新增一条数据,而实例对象是 find() 方法的结果,那么调用 save() 将更新表中现有的行。

查看在 vendor\yiisoft\yii2\db\BaseActiveRecord.php 文件中的代码

    /*
* 保存当前的记录
* 插入记录到数据表的一行,如果它的 isNewRecord 属性为 true(通常情况下使用 new 运算符来创建记录),
* 否则,将被用于更新表中的相应行(通常情况下使用 find 方法查找记录
*/
public function save($runValidation = true, $attributeNames = null)
{
if ($this->getIsNewRecord()) {
return $this->insert($runValidation, $attributeNames);
} return $this->update($runValidation, $attributeNames) !== false;
}

如上代码所示,通过判断 $this->getIsNewRecord() 方法的返回值,判断执行不同的操作。

最新文章

  1. 浅谈JavaScript之原型
  2. 查看abp框架异常信息
  3. rabbitmq批量删除队列
  4. 用GruntJS合并、压缩CSS资源文件
  5. maven搭建项目的时候,src/main/java无法建立的问题,提示信息The folder is already a source folder.(文件夹已经是源文件夹。)
  6. Copying Fields to a new Record
  7. php mysql_insert_id()
  8. 如何在Eclipse中配置Tomcat服务器
  9. Vijos 1493 传纸条
  10. php-GD库的函数(二)
  11. JS模式--状态模式(状态机)
  12. 【luogu P1396】营救
  13. Python 中的登陆获取数据跳转页面(不含数据库)
  14. ADO.NET之Parameter属性
  15. ThinkPHP 5.0/5.1 自定义404界面的配置
  16. Random Erasing Augmentation(REA)
  17. mui 动态加载数据出现的问题处理 (silder轮播组件 indexedList索引列表 下拉刷新不能继续加载数据)
  18. VeeamOne9.5-t添加监控服务器
  19. linux_文件夹实现挂载(必须在同一网段)
  20. SmartUpload文件上传组件的使用教程

热门文章

  1. jQuery里ready方法用原生js实现原理
  2. LVS+Nginx(LVS + Keepalived + Nginx安装及配置)
  3. JDBC用户访问被拒绝
  4. python面试的100题(20)
  5. layui时间控件laydate
  6. FactoryBean的作用
  7. pygame 浅解
  8. Pyarm的Pyqt的配置
  9. eclipse出错
  10. layui下拉框数据过万渲染渲染问题解决方案