我在我的应用程序中使用Yii和PostgreSQL以及PostGIS。我有一个带有“位置”字段的模型“用户”。 Location-field的内容对于人类来说毫无意义,但是Postgres可以使用ST_asText方法转换Location-field的值并将其转换为Longitude和Latitude。我已经在我的模型中为经度和纬度创建了虚拟字段。当我保存模型时,我使用beforeSave和afterSave方法将位置设置为正确的值。
我现在的问题是我希望在创建模型时填充纬度和经度虚拟字段(使用数据库中的现有对象)。我当时认为可能有类似beforeSelect和afterSelect的东西,我可以使用额外的计算列附加查询,因此能够在查询运行后处理从该额外列返回的值。
这有可能吗?
答案 0 :(得分: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();
}
答案 1 :(得分:0)
我在Yii2上遇到了这个问题,这就是我解决的方法。
覆盖AR的find()
方法并定义自己的ActiveQuery
类:
public static function find()
{
$query = new MyActiveQueryClass(get_called_class());
return $query->select('*, ST_AsGeoJSON(location) AS location');
}
在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就是这样。保存之前,请记住将经/纬度转换为正确的对象。我的是地理专栏。这是奖励:
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);
}