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

Only load includes which correspond to actual relationships (fix #1096) #1758

Open blmage opened 3 years ago

blmage commented 3 years ago

In my use case, I have a Language model, whose display name can be translated into any other language:

/**
 * @property int $id
 * @property string $code
 * @property-read string $self_display_name
 */
class Language extends RestfulModel
{
    protected $appends = [
        'self_display_name',
    ];

    /**
     * Returns the own displayable name of the language.
     *
     * @return string
     */
    public function getSelfDisplayNameAttribute(): string
    {
        return $this->getDisplayName($this->code);
    }

    /**
     * Returns a displayable name for the language, translated into another given language.
     *
     * @param string $languageCode
     * @return string
     */
    public function getDisplayName(string $languageCode): string
    {
        return Str::ucfirst(Str::lower(\Locale::getDisplayLanguage($this->code, $languageCode)));
    }
}

and a transformer that allows the client to specify the languages into which the display names should be translated:

class LanguageTransformer extends BaseTransformer
{
    protected $availableIncludes = [
        'displayNames',
    ];

    /**
     * @param Language $language
     * @param ParamBag|null $params
     * @return ResourceAbstract
     */
    public function includeDisplayNames(Language $language, ParamBag $params = null)
    {
        if (null === $params) {
            return $this->null();
        }

        $displayNames = [];
        $languageCodes = array_filter(array_map('trim', (array) $params->get('languages')));

        foreach ($languageCodes as $languageCode) {
            $displayNames[$languageCode] = $language->getDisplayName($languageCode);
        }

        return $this->primitive($displayNames);
    }
}

But because displayNames is not a relationship, queries fail whenever the corresponding include is requested.