YII2.0探究二:AR类和Query类的原理以及使用(一)

时间:2022-10-05 08:46:35

一、Yii\db\ActiveRecord 具体介绍:

  AR类即活动记录(Active Record)它的作用是 提供了一个面向对象的方式去操作数据库,从而对数据库进行CURD的时候可以 “复用”,这也就是体现了面向对象的好处。我们就从查询下手,看它封装的方法:

1.首先在models里面定义简单的数据库模型:

<?php
namespace app\models;
use yii\db\ActiveRecord;
class Content extends ActiveRecord{
public static function tableName(){
return 'user';
}
}
?>

2.在controller里面显示一个视图,并把操作打印出来:

<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\db\Query;
use app\models\Content;


class IndexController extends Controller{

public function actionRegister(){
$rows=Content::find()->all(); //查询方法
return $this->render('register',['data'=>$rows]);
}
}
?>

3.在视图中可以看出;

3 => 
object(app\models\Content)[64]
private '_attributes' (yii\db\BaseActiveRecord) =>
array (size=3)
'id' => string '4' (length=1)
'name' => string '大鱼海棠' (length=12)
'email' => string '665156@qq.com' (length=13)
private '_oldAttributes' (yii\db\BaseActiveRecord) =>
array (size=3)
'id' => string '4' (length=1)
'name' => string '大鱼海棠' (length=12)
'email' => string '665156@qq.com' (length=13)
private '_related' (yii\db\BaseActiveRecord) =>
array (size=0)
empty
private '_errors' (yii\base\Model) => null
private '_validators' (yii\base\Model) => null
private '_scenario' (yii\base\Model) => string 'default' (length=7)
private '_events' (yii\base\Component) =>
array (size=0)
empty
private '_behaviors' (yii\base\Component) =>
array (size=0)
empty

观察得出结论:
1.封装的是一个Object类型;
2.有着以下的方法:

_attributes,_validate,_related,_errors,_scenario,_events,_behavers,_validators

也就是说,这个数据表被抽象称为一个对象,里面包含着attributes字段属性,validators验证方法,related关联模型,所以我们得出以下几点:

  • 它的特点有:

    1. 每一个AR类关联一张数据表。
    2. 每个AR对象对应数据表中的一行,对象属性的Attribute映射到数据表中的对应列。
    3. 一条活动记录对应数据表中的一行。
  • 它继承的类有:

    yii\base\Model
    yii\base\Component
    yii\base\Object

  • 它封装的数据库操作:

    • 查询方法(两种):

      • yii\db\ActiveRecord::find()这个类继承yii\db\ActiveQuery因此它可以实现继承类的任意查询方式,比如where,orderBy,groupBy,join….一系列的查询方式;
      • yii\db\ActiveRecord::findBySql();
        params:string类型的sql语句,支持原生查询;
    • 增加:yii\db\ActiveRecord::save() // yii\db\ActiveRecord::insert()
      方法,配合find进行插入

    • 更新: yii\db\ActiveRecord::save()

    • 删除:yii\db\ActiveRecord::delete()


二、关于另一种数据库操作:yii\db\Query

  yii中操作数据库的类也有很多,例如yii\db\Query(PS:让我想起了当年的jQuery,嘲讽我们写的代码是意大利面条…..),那它的处理方式是什么样的呢?

<?php
namespace app\controller;
use Yii;
use yii\db\Query;

class siteController extends Controller{
$rows = (new \yii\db\Query())
->
select(['name','email'])
->
addSelect(['id'])
->
from('user')
->
where('id>:val')
->
addParams([':val'=>$val])
->
orderBy('id desc')
->
all();

$rows = (new Query())
->
select(['user.id','name','email','content.article'])
->
from('user')
->
join('LEFT JOIN','content','user.id=content.pid')
->
all();
}
?>

   从上面我们可以看出它的操作方式:select,对,你没猜错,它都是以->select() 开始的……….
  只针对于数据库中的读的操作, 封装了各种查询,不论是一个表,两个表,三个表。。。。一群表都可以查出来。(咳咳,查水表啦)。

(一)查询方式,总结下,我是个善于总结的人:

  1. 常规查询:select * from table where .. Group By .. Order By…limit…这种就是普通的查询需要熟悉sql
  2. 子查询(从2.0.1开始支持):

$subQuery = (new Query())->select('COUNT(*)')->from('user');
// SELECT `id`, (SELECT COUNT(*) FROM `user`) AS `count` FROM `post`
$query = (new Query())->select(['id', 'count' => $subQuery])->from('post');

3.联表查询
yii\db\Query::join([]);
参数:

 - '类型'     :'LEFT JOIN' 
- '连接表' :'tableName'
- '条件' : 'article.id='content.pid'

yii\db\Query::union();


$sql1='select....'
$sql2='select.....'
$sql1->union($sql2);

4. 批处理查询(解决大数据的查询问题)其他方式会把数据读取在内存上,批处理查询会利用数据游标 将数据以批为单位取出来

游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果。每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。百度百科

yii\db\Query::batch和yii\db\Query::each
参数:

  • params:int类型的数值,默认为100
use yii\db\Query;

$query = (new Query())
->from('user')
->orderBy('id');

foreach ($query->batch() as $users) {
// $users 是一个包含100条或小于100条用户表数据的数组
}

// or if you want to iterate the row one by one
foreach ($query->each() as $user) {
// $user 指代的是用户表当中的其中一行数据
}

(二)操作特点:

自己总结了几点:

  • 优雅性:由于主要是对数据库的查询封装,sql封装简单、明了,和原生类似,很容易去识别并上手。
  • 安全性:主要体现在where中,因为查询大部分都是从where去注入数据,因此存在很大的隐患,比如常见的SQL注入 or=or --hack等,让我们对于数据库的安全性要求极高。它的处理方式体现如下,:
    它对于数据的处理方式是当成一个整体去处理,我尝试输出’12adsad’、’ads12’、处理方式是:

    • 数字(int):原样处理;
    • 字符串(string):会截取前面的数字,不报错(如果条件不存在,则报错)。
    • 数字+字符串:数字在前截取数字,字符串在前忽略条件,并不报错。

“`
$val = ‘1 or 1 = 1’; // ‘adas125’,’dsads154’,’15’等等。

$model = (new \yii\db\Query())

                  ->select(['id','name'])

->where('age>:val')

->addParams([':val'=>$val]);

// $val为客户端传入的值。
  • 批处理:主要体现在对大数据的处理方面

三、两者的博弈: