当前位置:首页 > > 充电吧
[导读]首先看findOne的函数定义,该函数定义在BaseActiveRecord当中return static::findOne(['id' => $id, 'status' => self:

首先看findOne的函数定义,该函数定义在BaseActiveRecord当中


return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);


findOne定义是:


public static function findOne($condition)
{
     return static::findByCondition($condition)->one();
}


也就是说我们需要看一下findByCondition的函数的定义,该函数定义在BaseActiveRecord

protected static function findByCondition($condition)
{
    $query = static::find();

    if (!ArrayHelper::isAssociative($condition)) {
     // query by primary key
       $primaryKey = static::primaryKey();
       if (isset($primaryKey[0])) {
          $condition = [$primaryKey[0] => $condition];
        } else {
          throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
        }
    }
    return $query->andWhere($condition);
}


find函数的定义是在ActiveRecord类中定义的

public static function find()
{     
     return Yii::createObject(ActiveQuery::className(), [get_called_class()]);
}


也就是说$query是一个ActiveQuery的对象,其需要传入的参数是需要进行查询的类的名字"User"; 中间这一部分,先不要看,因为还没时间看,直接看下面的一行addWhere该函数的定义是在Query类中

public function andWhere($condition, $params = [])
{
    if ($this->where === null) {
       $this->where = $condition;
    } else {
       $this->where = ['and', $this->where, $condition];
    }
    $this->addParams($params);
    return $this;
}


在这里仅仅是将传入的参数$condition,付给ActiveQuery的where成员变量。到此findByCondition已经执行完成,开始执行one函数。该函数定义在ActiveQuery类当中

public function one($db = null)
{
    $row = parent::one($db);
    if ($row !== false) {
        $models = $this->populate([$row]);
        return reset($models) ?: null;
    } else {
        return null;
    }
}


首先调用父类Query的one函数,该函数定义如下:

public function one($db = null)
{
    return $this->createCommand($db)->queryOne();
}


这里就需要看一下createCommand函数,该函数的定义是:

public function createCommand($db = null)
{
    if ($db === null) {
        $db = Yii::$app->getDb();
    }
    list ($sql, $params) = $db->getQueryBuilder()->build($this);
    return $db->createCommand($sql, $params);
}

这里可以看到需要获得数据库链接配置,然后创建queryBuilder对象,并利用build模式构建完整的sql语句

public function build($query, $params = [])
{
   $query = $query->prepare($this);

   $params = empty($params) ? $query->params : array_merge($params, $query->params);

   $clauses = [
      $this->buildSelect($query->select, $params, $query->distinct, $query->selectOption),
      $this->buildFrom($query->from, $params),
      $this->buildJoin($query->join, $params),
      $this->buildWhere($query->where, $params),
      $this->buildGroupBy($query->groupBy),
      $this->buildHaving($query->having, $params),
    ];
    $sql = implode($this->separator, array_filter($clauses));
    $sql = $this->buildOrderByAndLimit($sql, $query->orderBy, $query->limit, $query->offset);
    if (!empty($query->orderBy)) {
        foreach ($query->orderBy as $expression) {
        if ($expression instanceof Expression) {
          $params = array_merge($params, $expression->params);  
            }
        }
    }
    if (!empty($query->groupBy)) {  
      foreach ($query->groupBy as $expression) {
         if ($expression instanceof Expression) {
            $params = array_merge($params, $expression->params);
            }
        }
    }

    $union = $this->buildUnion($query->union, $params);
    if ($union !== '') {
        $sql = "($sql){$this->separator}$union";
    }
    return [$sql, $params]; 
}



好吧,看看这个吧!!! 这一部分使用了build模式,进行创建整个sql语句下面的几个函数就先不说了,因为这一部分就是分部分进行构建查询语句,分部分构建select  from join   where group having  每个函数都构建了一部分语句,最后各个部分语句形成了$clauses是由各部分语句的数组。最后返回$sql, $param的数组,得到$sql之后可以继续执行了,,接下来创建$command

return $db->createCommand($sql, $params);


public function createCommand($sql = null, $params = [])
{
    /** @var Command $command */
    $command = new $this->commandClass([
     'db' => $this,
      'sql' => $sql,
    ]);

    return $command->bindValues($params);
}


bindValues函数如下:



public function bindValues($values)
{
    if (empty($values)) {
     return $this;
    }

    $schema = $this->db->getSchema();
    foreach ($values as $name => $value) {
       if (is_array($value)) {
         $this->_pendingParams[$name] = $value;
         $this->params[$name] = $value[0];
       } else {
         $type = $schema->getPdoType($value);
         $this->_pendingParams[$name] = [$value, $type];
         $this->params[$name] = $value;
        }
    }
    return $this;
}

先认为param是空的吧,这一路跟下来,脑袋都快炸了,接下来要执行的是,yiidbcommand类的queryOne函数

public function queryOne($fetchMode = null)
{
    return $this->queryInternal('fetch', $fetchMode);
}

queryInternal函数定义

protected function queryInternal($method, $fetchMode = null)
{
    $rawSql = $this->getRawSql();
    Yii::info($rawSql, 'yiidbCommand::query');
    if ($method !== '') {
       $info = $this->db->getQueryCacheInfo($this->queryCacheDuration, $this->queryCacheDependency);
       if (is_array($info)) {
           /* @var $cache yiicachingCache */
          $cache = $info[0];
          $cacheKey = [
          __CLASS__,
          $method,
          $fetchMode,
          $this->db->dsn,
          $this->db->username,
          $rawSql, 
            ];
          $result = $cache->get($cacheKey);
          if (is_array($result) && isset($result[0])) {
                Yii::trace('Query result served from cache', 'yiidbCommand::query');
                return $result[0];
            }
        }
    }

    $this->prepare(true);
    $token = $rawSql;
   try {
       Yii::beginProfile($token, 'yiidbCommand::query');
       $this->pdoStatement->execute();
       if ($method === '') {
           $result = new DataReader($this);
        } else {
           if ($fetchMode === null) {
              $fetchMode = $this->fetchMode;
            }
           $result = call_user_func_array([$this->pdoStatement, $method], (array) $fetchMode);
           $this->pdoStatement->closeCursor();
        }
        Yii::endProfile($token, 'yiidbCommand::query');
    } catch (Exception $e) {
        Yii::endProfile($token, 'yiidbCommand::query');
        throw $this->db->getSchema()->convertException($e, $rawSql);
    }

    if (isset($cache, $cacheKey, $info)) {
        $cache->set($cacheKey, [$result], $info[1], $info[2]);
        Yii::trace('Saved query result in cache', 'yiidbCommand::query');
    }
    return $result;
}

这样看来,就是讲所有的查询结果进行返回,那么会有人问不是findOne吗?在哪里进行的取one操作呢?是在ActiveQuery的one操作中,父类得到所有的查询结果,子类将查询结果进行reset操作,将第一行记录返回
查询总览: 所有的都是这样查询的static::findOne(条件),findOne函数定义是在BaseActiveRecord类中定义的,因为当前使用的User类的父类是ActiveRecord而ActiveRecord的父类是BaseActiveRecord 在此调用的是findByCondition在该函数中获得了ActiveQuery类的对象,同时传入需要修改的类的名称(需要调用该类的静态函数tableName,获得表名称),并且在findByCondition中将条件数组转成 String,方便继续使用,继续调用ActiveQuery的addWhere记录下ActiveQuery的where条件,之后调用Query的one()函数,在Query的one函数中创建了yiidbConnection类的对象,继续调用该db对象的getQueryBuilder函数,创建了一个QueryBuilder对象,然后在QUeryBuilder对象中进行完整的sql构造,将sql查询语句中可能出现的各个子查询都进行分别处理,各部分处理结果得到一个字符串,将这部分字符串组成数组,在展开implode,合成一个sql语句,将生成的sql语句传递给由yiidbConnection创建的yiidbcommand对象,并进行执行queryOne函数该函数调用queryInternal并返回结果集,最后由ActiveQuery的one函数进行reset操作,返回第一个结果记录






本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭