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

Understanding the ApiResource Attribute

Understanding the ApiResource Attribute

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

Now the ACTUAL work begins: our FIRST real Doctrine entity, Project, becomes a complete API through ONE attribute.

Creating the Project entity

docker compose exec php bin/console make:entity Project

EXACTLY the same make:entity command from the Symfony course (chapter 19) – fields: name (string, 255), description (text, nullable), createdAt (datetime_immutable).

Adding #[ApiResource]

api/src/Entity/Project.php
<?php

declare(strict_types=1);

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use App\Repository\ProjectRepository;
use Doctrine\ORM\Mapping as ORM;

#[ApiResource]
#[ORM\Entity(repositoryClass: ProjectRepository::class)]
class Project
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private string $name = '';

    #[ORM\Column(type: 'text', nullable: true)]
    private ?string $description = null;

    #[ORM\Column]
    private \DateTimeImmutable $createdAt;

    public function __construct()
    {
        $this->createdAt = new \DateTimeImmutable();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): static
    {
        $this->name = $name;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): static
    {
        $this->description = $description;

        return $this;
    }

    public function getCreatedAt(): \DateTimeImmutable
    {
        return $this->createdAt;
    }
}

EXACTLY ONE difference from a normal Symfony entity: the line #[ApiResource]. EVERYTHING ELSE (attributes, getters/setters) is IDENTICAL to the Symfony course.

Creating and applying a migration

docker compose exec php bin/console make:migration
docker compose exec php bin/console doctrine:migrations:migrate --no-interaction

EXACTLY the same five-step workflow from chapter 20 of the Symfony course – migrations work UNCHANGED in API Platform, since it's built on COMPLETELY NORMAL Doctrine/Symfony underneath.

What already works now

curl -k https://localhost/api/projects
{
  "@context": "/api/contexts/Project",
  "@id": "/api/projects",
  "@type": "hydra:Collection",
  "hydra:member": [],
  "hydra:totalItems": 0
}

An EMPTY list (no projects in the database yet), but a FULLY functioning endpoint – hydra:member is where the actual projects will appear once some exist (chapter 10).

How API Platform derives the endpoint name

/api/projects instead of /api/project: API Platform AUTOMATICALLY pluralizes the class name (Projectprojects) for collection endpoints – EXACTLY the same convention as MOST modern REST APIs, including the Magento REST API from our separate tutorials.

Tipp: php bin/console debug:router (EXACTLY as in the Symfony course, chapter 7) ALSO shows the routes AUTOMATICALLY generated by API Platform – useful for checking WHICH endpoints actually exist.