Skip to content

[Feature Request] Resource Expansion #1062

Description

@bwegrzyn

Would it be possible to add resource expansion as a feature to API Platform?

Basically, what I mean is that through resource expansion we can allow a user to specify which sub resources they want expanded on the resource they are requesting. For example, assuming we have a User->Group relation, when they request a User resource, they could pass a parameter with the request such as ?expand=group, and it would include the Group in the response. If they did not add ?expand=group then the group would not get included in the response unless it is part of the default groups as defined in the normalization context.

I've implemented by own basic resource expansion feature through the use of a ContextBuilder, but this is obviously pretty limited at the moment, and it does not support nested resources (eg. Users->Group->Owner by passing ?expand=group.owner.

Thoughts? I haven't done a whole lot of research in to this, so I'm not sure if it's possible to do just in API Platform or if it would require changes to the Symfony Serializer component.

use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
use Symfony\Component\HttpFoundation\Request;

class ContextBuilder implements SerializerContextBuilderInterface
{

    /**
     * @var SerializerContextBuilderInterface
     */
    private $decorated;

    public function __construct(SerializerContextBuilderInterface $decorated)
    {
        $this->decorated = $decorated;
    }

    public function createFromRequest(Request $request, bool $normalization, array $extractedAttributes = null) : array
    {
        $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);

        // Only allow expansions on normalization
        if (!$normalization) {
            return $context;
        }

        $permittedExpansions = $context['permitted_expansions'] ?? [];

        $requestedExpansions = (array) $request->query->get('@expand', []);

        // Support CSV format for single parameter
        if (count($requestedExpansions) === 1) {
            $requestedExpansions = explode(',', $requestedExpansions[0]);
        }

        foreach ($requestedExpansions as $expansion) {
            $expansion = trim($expansion);
            if (in_array($expansion, $permittedExpansions)) {
                if (!isset($context['groups'])) {
                    $context['groups'] = [];
                }

                $context['groups'][] = $expansion;
            }
        }

        return $context;
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions