首页 > 解决方案 > 按具有活动记录 yii2 的计算字段排序

问题描述

我有线程和线程上的消息

我想返回最后一条消息时间的所有线程,所以我在线程模型上添加了一个这样的新字段

  public function fields()
  { 
    $fields= ['idThread', 'idUser', 'title', 'unread', 'username','lastMesageTime'];
    return $fields;
   }

现在用这种方法我得到计算值 lastMessageTime

  public function getLastMessageTime()
   {
       return $this->hasMany(Messages::className(), ['idThread' => 'idThread'])
      ->select('time')->orderBy('time DESC')->limit(1)->scalar();
   }

在我的索引方法上使用这样的活动记录

return Thread::find()->select('idThread, title, idUser')->all();

这行得通,我得到了具有正确值的 lastMessageTime,但我想按顺序排序,这样我就可以得到第一个具有最新 lastMessageTime 的线程,我尝试使用以下代码

  public function scopes() {
    return array(
        'byOrden' => array('order' => 'lastTimeMessage DESC'),
    );
}

任何的想法?

编辑:这个解决方法有效,但我认为这不是一个好方法,因为我没有使用活动记录,所以我在线程模型上定义的用户名等字段我不得不再次获取它

 $query = (new \yii\db\Query());

    $query->select('*,  (SELECT max(time) as lastMessageTime  from messages where messages.idThread = thread.idThread ) lastMessageTime,
    (SELECT name from users where users.idUser = thread.idUser) as name ')
        ->from('threads')
        ->where(['idUser'=>$idUser])
        ->orderBy('lastMessageTime DESC');

    $rows = $query->all();
    return $rows;

标签: databaseactiverecordyii2

解决方案


您可以将额外的字段定义为模型属性,然后重写 find 方法为它们加载数据。

class Thread extends \yii\db\ActiveRecord
{
    public $lastMessageTime;

    public static function find()
    {
        $q = parent::find()
            ->select('*')
            ->addSelect(
                 new \yii\db\Expression(
                     '(SELECT max(time) FROM messages WHERE messages.idThread = thread.idThread) AS lastMessageTime'
                 );
        return $q;
    }
}

然后你可以像这样加载和订购模型:

$rows = Thread::find()->orderBy(['lastMessageTime' => SORT_DESC])->all();

推荐阅读