dingo / api

A RESTful API package for the Laravel and Lumen frameworks.
BSD 3-Clause "New" or "Revised" License
9.33k stars 1.25k forks source link

Question - how can i call available include in include ? #1661

Closed YannikFirre closed 4 years ago

YannikFirre commented 5 years ago

Hello,

I have this :

class DocumentController extends Controller
{
    public function index()
    {
        $documents = Document::all();

        return $this->response->collection($documents, new DocumentTransformer());
    }
}

class SourceTypeTransformer extends TransformerAbstract
{
    protected $availableIncludes = [
        'translations'
    ];

    public function transform(SourceType $type)
    {
        return $type->attributesToArray();
    }

    public function includeTranslations(SourceType $type)
    {
        return $this->primitive($type->getTranslationsArray());
    }
}

class DocumentTransformer extends TransformerAbstract
{
    protected $availableIncludes = [
        'sourceType',
    ];

    public function transform(Document $document)
    {
        return $document->attributesToArray();
    }

    public function includeSourceType(Document $document, ParamBag $params = null)
    {
        return $this->item($document->sourceType, new SourceTypeTransformer());
    }

}

If I add in the url the parameter "?include=sourceType" I have my sourceType object. But how can i call the "translations include" inside my SourceType Transformer ?

This it's not working : "?include=sourceType,translations"

This work but not the right way, i'm wrong ?

class DocumentTransformer extends TransformerAbstract
{
    ...

    public function includeSourceType(Document $document, ParamBag $params = null)
    {
        return $this->item($document->sourceType, new SourceTypeTransformer(['translations']));
    }
}

class SourceTypeTransformer extends TransformerAbstract
{
    ...

    public function __construct($includes = [])
    {
        if(!empty($includes)) {
           $this->defaultIncludes = array_merge($this->defaultIncludes, $includes);
        }
    }

    ...
}

Thanks for your help :)

YannikFirre commented 5 years ago

Any idea ?

specialtactics commented 5 years ago

Hi @InfinityWebMe

If I understand you correctly, it is just a simple matter of adding the additional include and it's function in your document transformer.

Read here for more info: https://fractal.thephpleague.com/transformers/ (This functionality is actually provided by Fractal, not Dingo).

YannikFirre commented 5 years ago

Hi @specialtactics,

I define my include in the transformer class (like includeSourceType in DocumentTransformer) and i add in the array "availableIncludes" not in the "defaultIncludes"I don't want the include to be called each time.

But i don't understand how to call dynamically this include when i use this in dingo : return $this->response->item($document, new DocumentTransformer());

This works : $request->merge(['include' => 'sourceType']); or with the construct function in my first post.

But it's a cleaner solution?

Thanks ;-)

SeoRoman commented 5 years ago

Actually I was just about to test this out myself, because I found this dingo/api that looks VERY promising for a future project... so I am going to be installing it now, and giving it a whirl... will let you know if I discover any better way to handle this..

specialtactics commented 4 years ago

@Yannik-Slym Essentially, anything you include in the URL string for "include" will be parsed, and if the transformer has that function, it will be called.

You can see how it works in this file /vendor/dingo/api/src/Transformer/Adapter/Fractal.php

And the docs I linked earlier, that's exactly what Dingo does: https://fractal.thephpleague.com/transformers/

If you want to also include properties of related model transformers or something like that, Fractal does nested recursion up to 10 levels deep (which is also modifiable).

So beyond this I am not 100% sure what the issue you are having is.

YannikFirre commented 4 years ago

Thank you that's what I understood later ;)