1

我在我的应用程序中将 Yii 与 PostgreSQL 和 PostGIS 一起使用。我有一个带有“位置”字段的模型“用户”。位置字段的内容对人类来说毫无意义,但是 Postgres 可以转换位置字段的值并使用 ST_asText 方法将其转换为经度和纬度。我在我的模型中为经度和纬度创建了虚拟字段。当我保存我的模型时,我使用 beforeSave 和 afterSave 方法将位置设置为正确的值。

我现在的问题是我希望在模型创建时填充纬度和经度虚拟字段(使用数据库中的现有对象)。我在想可能有类似 beforeSelect 和 afterSelect 之类的东西,我可以使用它们来附加查询与额外的计算列,因此能够在查询运行后处理从该额外列返回的值。

这有可能吗?

4

2 回答 2

1

我能够很容易地解决这个问题。当我应该一直在寻找 beforeFind 和 afterFind 时,我在 CActiveRecord 类中寻找 beforeSelect 和 afterSelect 方法。

我是这样做的。欢迎任何改进建议:)

public function beforeFind(){
    $criteria = new CDbCriteria;
    $criteria->select = "*,ST_asText(location) as location";
    $this->dbCriteria->mergeWith($criteria);
    return parent::beforeFind();
}

public function afterFind(){
    $location = str_replace('POINT(','',$this->location);
    $location = str_replace(')','',$location);
    $location = explode(" ", $location);

    $this->lon = $location[0];
    $this->lat = $location[1];
    return parent::afterFind();
}
于 2013-02-15T17:12:10.310 回答
0

我用 Yii2 遇到了这个问题,这就是我解决它的方法。

  1. 覆盖find()AR 的方法并定义您自己的ActiveQuery类:

    public static function find()
    {
        $query =  new MyActiveQueryClass(get_called_class());
        return $query->select('*, ST_AsGeoJSON(location) AS location');
    }
    
  2. afterFind()你将有 geo-json 并且你可以得到 lat/lng:

    public function afterFind()
    {
        parent::afterFind();
    
        $geoJson = json_decode($this->location, true);
        $this->lat = $geoJson['coordinates'][0];
        $this->lng = $geoJson['coordinates'][1];
    }
    

Yii2 就是这样。请记住在保存之前将您的 lat/lng 转换为正确的对象。我的是地理专栏。这是一个奖励:

public function beforeSave($insert)
{
    //create field as expression
    if(!empty($this->lat) && !empty($this->lng))
        $this->location = new \yii\db\Expression("'POINT({$this->lat} {$this->lng})'");

    return parent::beforeSave($insert);
}
于 2018-09-15T10:49:24.950 回答