• yii2之ActiveRecord 模型


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

    1. ActiveRecord 模型概述

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

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

    下面是一个 user 表的模型类

    <?php
    namespace commonmodels;
    
    use Yii;
    use yiidbActiveRecord;
    use yiiwebIdentityInterface;
    
    /**
     * 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() 方法查询返回的信息,如下:

    apimodelsUserRole Object
    (
        [_attributes:yiidbBaseActiveRecord: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:yiidbBaseActiveRecord: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:yiidbBaseActiveRecord:private] => Array
            (
            )
    
        [_relationsDependencies:yiidbBaseActiveRecord:private] => Array
            (
            )
    
        [_errors:yiiaseModel:private] => 
        [_validators:yiiaseModel:private] => 
        [_scenario:yiiaseModel:private] => default
        [_events:yiiaseComponent:private] => Array
            (
            )
    
        [_eventWildcards:yiiaseComponent:private] => Array
            (
            )
    
        [_behaviors:yiiaseComponent:private] => Array
            (
            )
    
    )
    

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

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

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

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

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

    查看在 vendoryiisoftyii2dbBaseActiveRecord.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() 方法的返回值,判断执行不同的操作。

  • 相关阅读:
    程序人生,编程思想
    CentOS Linux Jenkins安装、部署、更新
    Git常用命令
    U盘安装Mac OS X要点
    Shell执行*.sql
    WebStorm远程调试Node.js
    svn常用命令
    敏捷开发相关编辑思想(SOA、DDD、REST、CQRS)
    VisualVM远程监控Java
    centos搭建git服务
  • 原文地址:https://www.cnblogs.com/niuben/p/11062097.html
Copyright © 2020-2023  润新知