Created
October 10, 2016 17:18
-
-
Save ianevansDCGS/a0ef91a95347a1e334792615e88aa325 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @link http://www.yiiframework.com/ | |
* @copyright Copyright (c) 2008 Yii Software LLC | |
* @license http://www.yiiframework.com/license/ | |
*/ | |
namespace yii\data; | |
use Yii; | |
use yii\db\ActiveQueryInterface; | |
use yii\base\InvalidConfigException; | |
use yii\base\Model; | |
use yii\db\Connection; | |
use yii\db\QueryInterface; | |
use yii\di\Instance; | |
/** | |
* ActiveDataProvider implements a data provider based on [[\yii\db\Query]] and [[\yii\db\ActiveQuery]]. | |
* | |
* ActiveDataProvider provides data by performing DB queries using [[query]]. | |
* | |
* The following is an example of using ActiveDataProvider to provide ActiveRecord instances: | |
* | |
* ```php | |
* $provider = new ActiveDataProvider([ | |
* 'query' => Post::find(), | |
* 'pagination' => [ | |
* 'pageSize' => 20, | |
* ], | |
* ]); | |
* | |
* // get the posts in the current page | |
* $posts = $provider->getModels(); | |
* ``` | |
* | |
* And the following example shows how to use ActiveDataProvider without ActiveRecord: | |
* | |
* ```php | |
* $query = new Query(); | |
* $provider = new ActiveDataProvider([ | |
* 'query' => $query->from('post'), | |
* 'pagination' => [ | |
* 'pageSize' => 20, | |
* ], | |
* ]); | |
* | |
* // get the posts in the current page | |
* $posts = $provider->getModels(); | |
* ``` | |
* | |
* @author Qiang Xue <[email protected]> | |
* @since 2.0 | |
*/ | |
class ActiveDataProvider extends BaseDataProvider | |
{ | |
/** | |
* @var QueryInterface the query that is used to fetch data models and [[totalCount]] | |
* if it is not explicitly set. | |
*/ | |
public $query; | |
/** | |
* @var string|callable the column that is used as the key of the data models. | |
* This can be either a column name, or a callable that returns the key value of a given data model. | |
* | |
* If this is not set, the following rules will be used to determine the keys of the data models: | |
* | |
* - If [[query]] is an [[\yii\db\ActiveQuery]] instance, the primary keys of [[\yii\db\ActiveQuery::modelClass]] will be used. | |
* - Otherwise, the keys of the [[models]] array will be used. | |
* | |
* @see getKeys() | |
*/ | |
public $key; | |
/** | |
* @var Connection|array|string the DB connection object or the application component ID of the DB connection. | |
* If not set, the default DB connection will be used. | |
* Starting from version 2.0.2, this can also be a configuration array for creating the object. | |
*/ | |
public $db; | |
/** | |
* Initializes the DB connection component. | |
* This method will initialize the [[db]] property to make sure it refers to a valid DB connection. | |
* @throws InvalidConfigException if [[db]] is invalid. | |
*/ | |
public function init() | |
{ | |
parent::init(); | |
if (is_string($this->db)) { | |
$this->db = Instance::ensure($this->db, Connection::className()); | |
} | |
} | |
/** | |
* @inheritdoc | |
*/ | |
protected function prepareModels() | |
{ | |
if (!$this->query instanceof QueryInterface) { | |
throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.'); | |
} | |
$query = clone $this->query; | |
if (($pagination = $this->getPagination()) !== false) { | |
$pagination->totalCount = $this->getTotalCount(); | |
$query->limit($pagination->getLimit())->offset($pagination->getOffset()); | |
} | |
if (($sort = $this->getSort()) !== false) { | |
$query->addOrderBy($sort->getOrders()); | |
} | |
return $query->all($this->db); | |
} | |
/** | |
* @inheritdoc | |
*/ | |
protected function prepareKeys($models) | |
{ | |
$keys = []; | |
if ($this->key !== null) { | |
foreach ($models as $model) { | |
if (is_string($this->key)) { | |
$keys[] = $model[$this->key]; | |
} else { | |
$keys[] = call_user_func($this->key, $model); | |
} | |
} | |
return $keys; | |
} elseif ($this->query instanceof ActiveQueryInterface) { | |
/* @var $class \yii\db\ActiveRecord */ | |
$class = $this->query->modelClass; | |
$pks = $class::primaryKey(); | |
if (count($pks) === 1) { | |
$pk = $pks[0]; | |
foreach ($models as $model) { | |
$keys[] = $model[$pk]; | |
} | |
} else { | |
foreach ($models as $model) { | |
$kk = []; | |
foreach ($pks as $pk) { | |
$kk[$pk] = $model[$pk]; | |
} | |
$keys[] = $kk; | |
} | |
} | |
return $keys; | |
} else { | |
return array_keys($models); | |
} | |
} | |
/** | |
* @inheritdoc | |
*/ | |
protected function prepareTotalCount() | |
{ | |
if (!$this->query instanceof QueryInterface) { | |
throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.'); | |
} | |
$query = clone $this->query; | |
return (int) $query->limit(-1)->offset(-1)->orderBy([])->count('*', $this->db); | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function setSort($value) | |
{ | |
parent::setSort($value); | |
if (($sort = $this->getSort()) !== false && $this->query instanceof ActiveQueryInterface) { | |
/* @var $model Model */ | |
$model = new $this->query->modelClass; | |
if (empty($sort->attributes)) { | |
foreach ($model->attributes() as $attribute) { | |
$sort->attributes[$attribute] = [ | |
'asc' => [$attribute => SORT_ASC], | |
'desc' => [$attribute => SORT_DESC], | |
'label' => $model->getAttributeLabel($attribute), | |
]; | |
} | |
} else { | |
foreach ($sort->attributes as $attribute => $config) { | |
if (!isset($config['label'])) { | |
$sort->attributes[$attribute]['label'] = $model->getAttributeLabel($attribute); | |
} | |
} | |
} | |
} | |
} | |
} | |
Raw | |
PropertySearch.php | |
<?php | |
namespace api\modules\v1\models\search; | |
use api\modules\v1\models\Property; | |
use common\models\Suburb; | |
use common\models\Booking; | |
use common\models\Rate; | |
use common\models\PriceCategory; | |
use yii\data\ActiveDataProvider; | |
class PropertySearch extends Property | |
{ | |
public $suburb; | |
public $price_category; | |
public $radius; // Radius in meters to search around the latitude and longitude. | |
// now set the rules to make those attributes safe | |
public function rules() | |
{ | |
return [ | |
[['id', | |
'name', | |
'latitude', | |
'longitude', | |
'radius', | |
'slug', | |
'sleeps', | |
'single_rooms', | |
'double_rooms', | |
'bath', | |
'suburb', | |
'priceCategory', | |
'display'], | |
'safe'], | |
]; | |
} | |
/** | |
* Retrieves a list of models based on the current search/filter conditions. | |
* @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions. | |
*/ | |
public function search($params) | |
{ | |
$model = new Property; | |
$query = $model::find()->select(["*", 'distance' => '( | |
6371 * | |
acos( | |
cos( radians( :latitude ) ) * | |
cos( radians( latitude ) ) * | |
cos( | |
radians( longitude ) - radians( :longitude ) | |
) + | |
sin(radians(:latitude)) * | |
sin(radians(latitude)) | |
) | |
)']); | |
$query->addParams([':latitude' => (float)$this->latitude , ':longitude' => (float)$this->longitude]); | |
$dataProvider = new ActiveDataProvider([ | |
'query' => $query, | |
]); | |
//$query->joinWith('suburb'); | |
//$query->joinWith('priceCategory'); | |
if (!($this->load($params,'') && $this->validate())) { | |
return $dataProvider; | |
} | |
$query->andFilterWhere(['like', Property::tableName().'.id', $this->id]); | |
$query->andFilterWhere(['like', Property::tableName().'.name', $this->name]); | |
$query->andFilterWhere(['=',Property::tableName().'.display', $this->display]); | |
$query->andFilterWhere(['>=',Property::tableName().'.sleeps', $this->sleeps]); | |
$query->andFilterWhere(['>=',Property::tableName().'.double_rooms', $this->double_rooms]); | |
$query->andFilterWhere(['>=',Property::tableName().'.single_rooms', $this->single_rooms]); | |
$query->andFilterWhere(['>=',Property::tableName().'.bath', $this->bath]); | |
$query->where(['<', 'distance', $this->radius]); | |
// hard limit the results down to within 10km max of the search box. | |
// $query->andFilterWhere(['between', Property::tableName().'.latitude', ':latitude - (10.0 / 111.045)', ':latitude + (10.0 / 111.045)']); | |
// $query->andFilterWhere(['between', Property::tableName().'.longitude', ':longitude - (10.0 / (111.045 * COS(RADIANS(:latitude))))', ':longitude + (10.0 / (111.045 * COS(RADIANS(:latitude))))' ]); | |
// Related Suburb and Price Category Data | |
$query->andFilterWhere(['=', Suburb::tableName().'.id', $this->suburb]); | |
$query->andFilterWhere(['=', PriceCategory::tableName().'.id', $this->price_category]); | |
//var_dump($query);exit; | |
$dataProvider->sort->attributes['suburb'] = [ | |
'asc' => ['suburb.name' => SORT_ASC], | |
'desc' => ['suburb.name' => SORT_DESC], | |
]; | |
$dataProvider->sort->attributes['priceCategory'] = [ | |
'asc' => ['priceCategory.name' => SORT_ASC], | |
'desc' => ['priceCategory.name' => SORT_DESC], | |
]; | |
return $dataProvider; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment