Using cursors with fractal to paginate content
So I am using the fractal package to build an API and recently having trouble with pagination. I'll try to give a basic but accurate example of my code. The Cursor implementation is working fine and all the problem is in the query I think.
So basically I have this:
public function trainers($query, Request $options)
{
$howMany = $options->get('howMany', 20);
$current = base64_decode( (string) $options->get('cursor', false));
$country = $options->get('country', '*');
$tableJoins = $this->defineTableJoins($country);
$filteredResults = $this->resolveSearchFilters($tableJoins, $options);
$trainers = $this->makeSearch($filteredResults, $query, $howMany);
if( ! $current ) return $trainers->get( $this->fieldsToDisplay() );
return $trainers->where('users.created_at', '>', $current)->get( $this->fieldsToDisplay() );
}
private function defineTableJoins($country)
{
return User::isActive()
->whereHas('roles', function($query){
$query->where('name', 'trainer');
})
->join('trainers', 'users.userable_id', '=', 'trainers.id')
->leftJoin('city_trainer', 'trainers.id', '=', 'city_trainer.trainer_id')
->leftJoin('cities', 'cities.id', '=', 'city_trainer.city_id')
->join('regions', 'regions.id', '=', 'trainers.region_id')
->join('countries', 'users.country_id', '=', 'countries.id')
->where('regions.country_code', $country);
}
private function matchSearchQuery($query)
{
$results = function($q) use ($query) {
$q->where('users.name', 'LIKE', "%{$query}%")
->orWhere('regions.name', $query)
->orWhere('cities.name', 'LIKE', "%{$query}%")
->orWhere('trainers.zip_code', $query);
};
return $results;
}
private function makeSearch($filteredResults, $query, $howMany)
{
$result = $filteredResults->where( $this->matchSearchQuery($query) )
->distinct()
// ->orderBy('trainers.pro_member', 'DESC');
// ->orderBy('users.is_atiiv', 'DESC')
// ->orderBy('trainers.pro_member', 'DESC')
->orderBy('users.created_at', 'ASC')
->take($howMany);
return $result;
}
private function fieldsToDisplay()
{
return [
'users.*',
'regions.name as region',
'countries.printable_name as country',
'trainers.accepting_clients as accepting_clients',
'trainers.pro_member as pro_member'
];
}
In the trainers() function the cursor that I'm using is the created_atfield (transformed to a string with Carbon). So if the cursor is defined I try to fetch the next 20 trainers that have a created_atdate bigger then the one provided.
Then the makeSearch() method orders the results by the created_at field and everything works fine.
The problem is when I add another orderBy, to show first the pro_members.
If I first order by the created_at date the pro members will not show up in first and if I order by pro_membersfirst I won´t be able to get all records.
Pleaase help, going crazy with this ...
Please or to participate in this conversation.