yii2之碎文集合 / 解析Query中的indexBy和column方法

阿北哥ya 619次阅读

对于数据表user,当想要得到如下结果的时候

[
    1=>'abei',
    2=>'abei2017',
    11=>'abei2018'
]
// id=>username

我们一般会这样做

ArrayHelper::map(User::find()->all(),'id','username')

这没有任何问题,但是现在我们要在yii2内部寻找另一个方法,找到了,如下

User::find()->select(['username'])->indexBy('id')->column()

接下来我们就来探究上述写法的原理

你的疑惑一定是:既然select中没有id,id是怎么出现的。

好,我们从代码入手,秘密就在/vendor/yiisoft/yii2/db/Query.php 的column方法中

public function column($db = null){
    ....
    if (is_string($this->indexBy) && is_array($this->select) && count($this->select) === 1) {
        if (strpos($this->indexBy, '.') === false && count($tables = $this->getTablesUsedInFrom()) > 0) {
            $this->select[] = key($tables) . '.' . $this->indexBy;
        } else {
            $this->select[] = $this->indexBy;
        }
    }
    ....
}

当满足三个条件的时候,就能让column方法为select添加其他项

当以上条件满足后,Query类会将indexBy方法的参数添加到select数组中,此刻select中有两个值了。

解决了select中值的疑惑,我想你一定会说那为何最后结果中indexBy中的参数变成了数组的key值?

我们继续说,秘密还是在column方法中,看下面代码

public function column($db = null){
    ....
    $rows = $this->createCommand($db)->queryAll();
    $results = [];
    foreach ($rows as $row) {
        $value = reset($row);

        if ($this->indexBy instanceof \Closure) {
            $results[call_user_func($this->indexBy, $row)] = $value;
        } else {
            $results[$row[$this->indexBy]] = $value;
        }
    }

    return $results;
    ....
}

我们来看一看逻辑

  1. 执行数据库操作得到结果$rows
  2. 自己定义一个变量$results并将处理后的$rows赋值给它
  3. 将$results作为最后的结果

就是第2步解决了我们的疑惑,在上面的例子中,此刻的select是一个数组['username','id']

  1. 通过reset方法拿到一条记录中的username值
  2. 如果indexBy是字符串,则将$value赋值给$results[$row[$this->indexBy]],此刻的$row[$this->indexBy] == $row['id'] == 1、2、3、11.....
  3. 最后你得到了id=>username数组

解析完毕,听懂了么?感谢浏览。

此文编号为425 上次更新于2个月前 / Yii 频道
相关文章
留言
小提醒 欢迎大家留言并且我会拿出时间去看,当然我会删除那些被视为垃圾或广告的留言。
1-1条,共1条数据.
        
1个月前
#1105

听懂了,感谢大神发帖

客气。

首页 登录 / 注册