3

I want to create a model like this.

{
  "id": 7653,
  "name": "Vortl 123",
   "category": [
    {
      "name": "Electronic",
      "url": "electronic",
      "id": 1
    }, {
      "name": "Phone",
      "url": "phone",
      "id": 2
    },
    {
      "name": "Mobile Phone",
      "url": "mobile-phone",
      "id": 3
    }
}

I created documents with using doctrine odm references. Codes are these.

This is product class.

/**
 * @ApiResource
 *
 * @Document
 */
class Product
{

    /**
     * @ODM\Id(strategy="INCREMENT", type="integer")
     */
    private $id;

    /**
     * @ODM\Field(type="string")
     * @Assert\NotBlank
     */
    public $name;

    public function __construct()
    {
        $this->categories = new ArrayCollection();
    }

    /**
     * @ODM\ReferenceMany(targetDocument=Category::class, inversedBy="product", cascade={"persist"}, storeAs="id")
     */
    public $categories;

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


    /**
     * @param Category $category
     */
    public function addCategory(Category $category): void
    {
        $this->categories->add($category);
    }

    public function removeCategory(Category $category): void
    {

        $category->product = null;
        $this->categories->removeElement($category);
    }

and my category class is.

/**
 * @ApiResource
 *
 * @ODM\Document
 */
class Category
{

    /**
     * @ODM\Id(strategy="INCREMENT", type="integer")
     */
    private $id;

    /**
     * @ODM\ReferenceOne(targetDocument=Product::class, mappedBy="categories", storeAs="id")
     */
    public $product;


    /**
     * @ODM\Field(type="string")
     * @Assert\NotBlank
     */
    private $name;


    /**
     * @ODM\Field(type="string")
     */
    private $url;


    /**
     * @return mixed
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @param mixed $id
     */
    public function setId($id): void
    {
        $this->id = $id;
    }




    /**
     * @return mixed
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param mixed $name
     */
    public function setName($name): void
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * @param mixed $url
     */
    public function setUrl($url): void
    {
        $this->url = $url;
    }


}

It works correct. When I can post category and get them. Then I post product and add categories to product via iri reference. The problem is I see the categories id instead of categories object like this.

{
    "@context": "/api/contexts/Product",
    "@id": "/api/products/17",
    "@type": "Product",
    "name": "Product17",
    "categories": [
        "/api/categories/1",
        "/api/categories/2",
        "/api/categories/3"
    ]
}

I create category with post method then I create product with post method. To add category to product, I'm using iri reference like /api/categories/1 in the post method of product.

I don't understand why it is showing with iri reference? I want object of those iri references in the example that I want. Can anyone help me?

nogabemist
  • 402
  • 5
  • 29

1 Answers1

5

You must add at minimum one group normalizationContext:

<?php

/**
 * @ApiResource(
 *     normalizationContext={"groups" = {"product:read"}}
 * )
 *
 * @Document
 */
class Product
{

    /**
     * @ODM\Id(strategy="INCREMENT", type="integer")
     */
    private $id;

    /**
     * @ODM\Field(type="string")
     * @Assert\NotBlank
     * @Groups({"product:read"})
     */
    public $name;

    // ...
}

and Category:

<?php

/**
 * @ApiResource
 *
 * @Document
 */
class Category
{
    // ...

    /**
     * @ODM\Field(type="string")
     * @Assert\NotBlank
     * @Groups({"product:read"})
     */
    public $name;

    // ...
}

After that you should see Category's objects with property $name

Winzza
  • 562
  • 3
  • 9
  • 1
    Yes, It's the best way to do – faso-dev Mar 04 '20 at 10:03
  • Sorry, I'm new. I didn't get the logic. why you used group annotation in product name? The only problem I have is category collection. Category collection still comes with iri reference instead of object while I'm doing it just like you did. – nogabemist Mar 04 '20 at 12:07
  • 1
    I think you need to read the documentation https://api-platform.com/docs/core/serialization/#embedding-relations. In short, you need to add the same group to “Product” (for all operations or one operation) and to “Category” in all the properties that you want to see in the answer. – Winzza Mar 04 '20 at 12:35
  • Oh the documentation and your answers helped me to understand and solve. Thank you. – nogabemist Mar 04 '20 at 12:55