Magento 2 Experten — Hyvä Theme, Tailwind CSS & SEO aus einer Hand ›

Nested Collections: /api/projects/{id}/tasks

Nested Collections: /api/projects/{id}/tasks

~14 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026

ALONGSIDE /api/tasks (ALL tasks), a SECOND endpoint that returns ONLY the tasks of ONE specific project is often useful – EXACTLY what nested ("sub-resource") operations are for.

Defining a nested operation

api/src/Entity/Task.php
use ApiPlatform\Metadata\GetCollection;

#[ApiResource(
    normalizationContext: ['groups' => ['task:read']],
    denormalizationContext: ['groups' => ['task:write']]
)]
#[ApiResource(
    uriTemplate: '/projects/{projectId}/tasks',
    uriVariables: [
        'projectId' => new \ApiPlatform\Metadata\Link(
            fromClass: Project::class,
            toProperty: 'project',
        ),
    ],
    operations: [new GetCollection()],
    normalizationContext: ['groups' => ['task:read']]
)]
#[ORM\Entity(repositoryClass: TaskRepository::class)]
class Task
{
    // ... unchanged
}

TWO #[ApiResource] attributes on the SAME class – the FIRST defines the "flat" /api/tasks resource from chapter 37, the SECOND an ADDITIONAL, nested view on the SAME data.

Link describes HOW the {projectId} placeholder gets connected to a real database query: fromClass: Project::class says THAT projectId is a Project ID, toProperty: 'project' says THAT the Task side gets filtered via the project property.

Testing the nested endpoint

curl -k https://localhost/api/projects/1/tasks
{
  "@context": "/api/contexts/Task",
  "@id": "/api/projects/1/tasks",
  "@type": "hydra:Collection",
  "hydra:member": [
    {"@id": "/api/tasks/1", "title": "Create wireframes", "done": false}
  ],
  "hydra:totalItems": 1
}

ONLY tasks belonging to project 1 – EXACTLY the same filtering as manually using ?project=/api/projects/1 (chapter 31 could also be used for that), but as its OWN, more descriptive path.

Achtung: Calling /api/projects/999/tasks with a NON-existent projectId returns 404 Not Found – API Platform AUTOMATICALLY checks whether the parent project exists BEFORE querying the task collection.

Tipp: ALL filters/pagination/sorting from block 4 ALSO work on nested collections – /api/projects/1/tasks?order[title]=asc is JUST AS valid as on the flat /api/tasks resource.