Core: different normalization context for subresource

Created on 8 Jan 2019  路  2Comments  路  Source: api-platform/core

I have two resource, province and city that city is sub resource of province.

/**
 * @ApiResource(
 *     attributes={"pagination_enabled"=false},
 *     collectionOperations={
 *          "get"={"normalization_context"={"groups"={"province"}}},
 *          "api_provinces_counties_get_subresource"={
 *              "pagination_enabled"=false,
 *              "method"="get",
 *              "normalization_context"={"groups"={"county", "province"}},
 *          },
 *      },
 *     itemOperations={"get"},
 *     subresourceOperations={
 *          "api_provinces_cities_get_subresource"={
 *              "pagination_enabled"=false,
 *              "method"="get",
 *              "normalization_context"={"groups"={"city"}, "enable_max_depth"=true}
 *          }
 *     }
 * )
 */
class Province
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     *
     * @Groups({"province"})
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=50)
     *
     * @Groups({"province"})
     */
    private $name;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="County", mappedBy="province")
     *
     * @ApiSubresource(maxDepth=1)
     *
     * @Groups({"province:county"})
     */
    private $counties;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="City", mappedBy="province")
     *
     * @ApiSubresource(maxDepth=1)
     *
     * @Groups({"province:cities"})
     * @MaxDepth(1)
     */
    private $cities;

and

/**
 * @ApiResource(
 *     attributes={"pagination_enabled"=false},
 *     collectionOperations={},
 *     itemOperations={"get"},
 *     normalizationContext={"groups"={"city", "city:province", "city:county", "province"}, "enable_max_depth"=true}
 * )
 */
class City
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     *
     * @Groups({"city"})
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=50)
     *
     * @Groups({"city"})
     */
    private $name;

    /**
     * @var Province
     *
     * @ORM\ManyToOne(targetEntity="Province", inversedBy="cities")
     * @ORM\JoinColumn(name="province_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
     *
     * @Groups({"city:province"})
     * @MaxDepth(1)
     */
    private $province;

I want on request /provinces/16/cities it return only city (province information is useless, the client know it) and when client request for a city information(e.g: search) /cities/620 it return city & province information.

How can i do that?
does platform support it?

Most helpful comment

See: https://api-platform.com/docs/core/operations/#subresources

You may want custom groups on subresources. Because a subresource is nothing more than a collection operation, you can set normalization_context or denormalization_context on that operation. To do so, you need to override collectionOperations. Based on the above operation, because we retrieve an answer, we need to alter it's configuration:

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

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;

/**
 * @ApiResource(collectionOperations={
 *     "api_questions_answer_get_subresource"={
 *         "method"="GET",
 *         "normalization_context"={"groups"={"foobar"}}
 *     }
 * })
 */
class Answer
{
    // ...
}

All 2 comments

See: https://api-platform.com/docs/core/operations/#subresources

You may want custom groups on subresources. Because a subresource is nothing more than a collection operation, you can set normalization_context or denormalization_context on that operation. To do so, you need to override collectionOperations. Based on the above operation, because we retrieve an answer, we need to alter it's configuration:

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

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiResource;

/**
 * @ApiResource(collectionOperations={
 *     "api_questions_answer_get_subresource"={
 *         "method"="GET",
 *         "normalization_context"={"groups"={"foobar"}}
 *     }
 * })
 */
class Answer
{
    // ...
}

@dawsza Thanks a lot for linking this specific part of the documentation.
In fact, I had already read it but I didn't realize that the collectionOperations was to be configured on the subresource entity, not on the "parent" entity!

Is it just me or the docs is not really clear on this point?

Anyway, thanks a lot for your help ;)

Was this page helpful?
0 / 5 - 0 ratings