Laravel-json-api: Question: sorting by included resource

Created on 9 Jan 2018  路  2Comments  路  Source: cloudcreativity/laravel-json-api

Heyhey.
At first: Thank you very much for this great package! It already made so many things so much easier for me!

Now my Question:
I have a project with a couple of resources, based on Eloquent models, similar to the following example:

Car:

  • name
  • color
  • weight
  • speed

People:

  • name
  • address
  • car ( hasOne("AppCar") )

The People are so many, that i must use pagination.
When I now call "api/v1/people?include=cars" I get all the people, together with their cars. easy.
But what I need in addition, is to sort the people by the name of their car. Like this: "api/v1/people?include=cars&sort=cars.name".

Is there any way to do this? Or does anyone has an idea for a workaround?

Most helpful comment

Thank you dimitvassilev! I've found a working solution in this issue https://github.com/cloudcreativity/laravel-json-api/issues/77 i must have overlooked it yesterday.
The way is to overload the orderBy function so that it does actually the same what you describe: join the related table and apply the orderBy afterwards. I've only added the selectRaw to the query, because it somehow joined the ids and other columns from the related table onto the primary table.

in the Adapter

`    use Neomerx\JsonApi\Contracts\Encoder\Parameters\SortParameterInterface;

`    /**
     * Sorting by related columns
     * @param Builder $query
     * @param SortParameterInterface $param
     */
    protected function sortBy(Builder $query, SortParameterInterface $param)
    {
        $column = $this->getQualifiedSortColumn($query, $param->getField());
        $order = $param->isAscending() ? 'asc' : 'desc';
        if (!starts_with($column, $query->getModel()->getTable())) {
            // related sorting
            $relation = substr($column, 0, strpos($column, '.'));
            $attribute = substr($column, strlen($relation) + 1);
            $relation = $query->getModel()->$relation();
            $relatedTable = $relation->getRelated()->getTable();
            // Include related table
            $query->selectRaw($query->getModel()->getTable().".*")->leftJoin(
                $relatedTable,
                $query->getModel()->getTable().'.'.$relation->getForeignKey(),
                '=',
                $relatedTable.'.'.$relation->getOwnerKey()
            );
            // correct column name to match model table
            $column = $relatedTable.'.'.$attribute;
        }
        $query->orderBy($column, $order);
    }`

All 2 comments

Hi,
I am currently just getting acquainted with the library, so I am not sure for the best way to integrate such a functionality (or even if it isn't provided out-of-the-box) - probably through some method in the adapter classes. As to ideas - take a look at the implementation for sorting via attributes of related resources in this library https://github.com/andersao/l5-repository. Look for the 'Sorting through related tables' section in the README for some explanation. Basically, you have to build a query in which the related model's table is first joined to the current model's table and then apply the sorting criteria with the necessary related resource's column, qualified with the related table name.

Thank you dimitvassilev! I've found a working solution in this issue https://github.com/cloudcreativity/laravel-json-api/issues/77 i must have overlooked it yesterday.
The way is to overload the orderBy function so that it does actually the same what you describe: join the related table and apply the orderBy afterwards. I've only added the selectRaw to the query, because it somehow joined the ids and other columns from the related table onto the primary table.

in the Adapter

`    use Neomerx\JsonApi\Contracts\Encoder\Parameters\SortParameterInterface;

`    /**
     * Sorting by related columns
     * @param Builder $query
     * @param SortParameterInterface $param
     */
    protected function sortBy(Builder $query, SortParameterInterface $param)
    {
        $column = $this->getQualifiedSortColumn($query, $param->getField());
        $order = $param->isAscending() ? 'asc' : 'desc';
        if (!starts_with($column, $query->getModel()->getTable())) {
            // related sorting
            $relation = substr($column, 0, strpos($column, '.'));
            $attribute = substr($column, strlen($relation) + 1);
            $relation = $query->getModel()->$relation();
            $relatedTable = $relation->getRelated()->getTable();
            // Include related table
            $query->selectRaw($query->getModel()->getTable().".*")->leftJoin(
                $relatedTable,
                $query->getModel()->getTable().'.'.$relation->getForeignKey(),
                '=',
                $relatedTable.'.'.$relation->getOwnerKey()
            );
            // correct column name to match model table
            $column = $relatedTable.'.'.$attribute;
        }
        $query->orderBy($column, $order);
    }`
Was this page helpful?
0 / 5 - 0 ratings

Related issues

osteel picture osteel  路  3Comments

dklesev picture dklesev  路  4Comments

tembra picture tembra  路  6Comments

umbert-cobiro picture umbert-cobiro  路  4Comments

tekord picture tekord  路  3Comments