将 SQL 查询计算出的字段添加到 Yii2 ActiveRecord 模型中

TMo*_*gan 6 yii2 yii2-model

我正在编写代码以返回位于指定区域内并接近某个纬度和经度的位置列表。数据库布局是有一个包含企业的 Location 表、一个定义区域的 Region 表(UrlName 是标识区域的 slug),以及一个 regionLocation 表,将区域映射到位置。

SQL 查询非常繁琐,但它计算了一个名为“距离”的虚拟列,我希望在返回的模型中可以访问该列。

这是出现在我的位置模型中的代码的缩短版本:

        public static function getByRegionAndLatLong( $regionName, $lat, $long ) {

        $sql = "SELECT
            `Location`.`LocationId`,
            `Location`.`Latitude`,
            `Location`.`Longitude`,
                    (
                    3959 * acos (
                    cos ( radians( :Latitude ) )
                    * cos( radians( latitude ) )
                    * cos( radians( longitude ) - radians( :Longitude ) )
                    + sin ( radians( :Latitude ) )
                    * sin( radians( latitude ) )
                    )
                  ) AS Distance
                FROM Location
                    LEFT JOIN RegionLocation RL
                    ON RL.LocationId = Location.LocationId
                    LEFT JOIN Region R
                    ON R.RegionId = RL.RegionId
                WHERE R.UrlName= :UrlName
                ORDER BY Distance ;
        ";

        return Location::findBySql( $sql, [
            ':Latitude' => $lat,
            ':Longitude' => $long,
            ':UrlName' => $UrlName
        ] )->all();
    }
Run Code Online (Sandbox Code Playgroud)

问题是,当我运行查询时,我希望将计算出的“距离”列包含在结果中。但是,由于数据库中没有名为“Distance”的实际字段,Yii2 的 ActiveRecord 类不会将该字段添加到生成的模型中。

我可以通过在位置表中创建一个名为“距离”的列来解决它,但我希望有一种方法可以在不更改数据库的情况下做到这一点。

我的最终目的是让模型返回一个 Location 对象数组,每个 Location 对象都有一个“距离”属性。然后,控制器将使用类似于以下的代码生成一个 json 提要:

    public function actionGetStudiosByLatLong( $regionName = '', $latitude='', $longitude='') {
        \Yii::$app->response->format = 'json';

        return Location::getByRegionAndLatLong( $regionName, $latitude, $longitude );
    }
Run Code Online (Sandbox Code Playgroud)

soj*_*oju 7

您应该简单地将此属性添加到您的类中:

class Location extends \yii\db\ActiveRecord
{

    public function attributes()
    {
        // add distance attribute (will work for json output)
        return array_merge(parent::attributes(), ['Distance']);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

阅读有关选择额外字段的更多信息。