Symfony 5 API populate related object entities

Viewed 1054

I am trying to create a simple web app using Symfony 5. I am using the API.

Currently when calling some endpoint it only displays the IRI link to the related link:

I need instead to display the related entity object itself; if I get the Item endpoint the related entity Program should be returned this:

{
    "id": 1,
    "program": {
        "id": 1,
        "name": "First program"
    },
    "description": "fgdfg",
    "comment": "dfgdfg"
{

So, this is how the table looks:

I thought setting up a subresource would be enough to get the object but it wasn't:

  1. In the InventoryItem entity configured @ApiSubresource annotation of the Program property:

    /**
     * @ORM\ManyToOne(targetEntity=Program::class, inversedBy="inventoryItems")
     * @ORM\JoinColumn(nullable=false)
     * @ApiSubresource
     */
    private $program;
    
  2. In resources.yaml file I configured the subresource:

    App\Entity\InventoryItem:
       properties:
           program:
               subresource:
                   resourceClass: 'App\Entity\Program'
                   collection: true
    

This still returns the IRI instead of the object, The only thing that has changed was that now I can access to the related entity for the current object in this URL: http://localhost:8000/api/inventory_items/1/program.json.

Any idea on how to return the related entity object itself instead of the IRI URL?

1 Answers

You're searching to serialize your item. So I guess this is more a serialization problem than a sub-resource problem. I think you should use serialization group instead of SubResource.

SOLUTION1 Serialize the embedding relation

The "Embedding relation" provides an example with Book and Author.

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

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource(normalizationContext={"groups"={"item"}})
 */
class Item
{
    /**
     * @Groups({"item"})
     */
    public $description;

    /**
     * @Groups({"item"})
     */
    public $comment;

    /**
     * @Groups({"item"})
     */
    public $program;

    // ...
}

// api/src/Entity/Person.php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;
use Symfony\Component\Serializer\Annotation\Groups;

/**
 * @ApiResource
 */
class Person
{
    /**
     * ...
     * @Groups("item") <=== This is item, not program but you can have two groups
     */
    public $name;

    // ...
}

SOLUTION2 Mix subresources and serialization groups

This example should work, but (if subresources are necessary) you can mixed subresources and serializations too, but in you case I guess that the first solution is the best.

Related