Sort using related properties
jcvalerio opened this issue · comments
Hi !
For example I have to entities
Races and Distance
A race have one distance.
So, when I request races order by distance.Quantity (integer number that represent for instance 10 miles) and StartingDate(date on race entity), I expect as a result:
- races order first by distance.Quantity
- then order by StartingDate
This is the request uri
http://server/api/race/?sort=[{"property":"distance.Quantity","direction":"ASC"},{"property":"StartingDate","direction":"ASC"}]
We are getting this query as a result
SELECT `t`.`RaceId` AS `t0_c0`,
`t`.`DistanceId` AS `t0_c3`,
`t`.`StartingDate` AS `t0_c4`,
`t`.`StartingTime` AS `t0_c5`,
`distance`.`DistanceId` AS `t2_c0`,
`distance`.`Name` AS `t2_c1`,
`distance`.`Quantity` AS `t2_c3`
FROM `Race` `t`
LEFT OUTER JOIN `Distance` `distance` ON (`t`.`DistanceId`=`distance`.`DistanceId`)
ORDER BY t.StartingDate ASC LIMIT 100
As you can see, distance.Quantity was not added as part of the ORDER By statement.
Is it possible to use in this way? or am I doing something wrong?
I was looking at /RestfullYii/ARBehaviors/ERestHelperScopes.php
The orderBy
method, and the way on how the statement is build
public function orderBy($field, $dir = 'ASC')
{
...
$this->Owner->getDbCriteria()->mergeWith(
...
$alias = $this->Owner->getTableAlias(false, false); //<-- this is a string index 'distance'*
$dbCriteria['with'][$alias] = []; //<-- here the array is build ['distance' => 0]
$dbCriteria['with'][$alias]['order'] = (!empty($dbCriteria['with'][$alias]['order'])? ', ': '') . $this->getSortSQL($property, $orderListItem['direction'], $alias);
..
}
Then I debug the /yiisoft/yii/framework/db/schema/CDbCriteria.php
to figure out why the property was not included.
public function mergeWith($criteria,$operator='AND')
{
...
if(empty($this->with))
$this->with=$criteria->with;
elseif(!empty($criteria->with))
{
$this->with=(array)$this->with;
foreach((array)$criteria->with as $k=>$v)
{
if(is_integer($k)) //<-- here is looking for an integer index
$this->with[]=$v;
elseif(in_array($k, $this->with)) //<-- here the array is [0 => 'distance']
{
$excludes=array();
foreach(array('joinType','on') as $opt)
{
if(isset($this->with[$k][$opt]))
$excludes[$opt]=$this->with[$k][$opt];
if(isset($v[$opt]))
$excludes[$opt]= ($opt==='on' && isset($excludes[$opt]) && $v[$opt]!==$excludes[$opt]) ?
"($excludes[$opt]) AND $v[$opt]" : $v[$opt];
unset($this->with[$k][$opt]);
unset($v[$opt]);
}
$this->with[$k]=new self($this->with[$k]);
$this->with[$k]->mergeWith($v,$operator);
$this->with[$k]=$this->with[$k]->toArray();
if (count($excludes)!==0)
$this->with[$k]=CMap::mergeArray($this->with[$k],$excludes);
}
else
$this->with[$k]=$v;
}
}
I just get
- When
with
is build onorderBy
atERestHelperScopes.php
, a string index is used. - When
CDbCriteria.php
try to parse thewith
array, it looks for an integer index, or for a different arrangement of values on the array.
@jcvalerio :> Hmm... This is very strange... You should be able to do this and in fact it is test covered... I will look into it but it I may not be able to replicate your situation. Let me know if you are able to resolve this on your own.