0

I'm a young developer and I recently discover Api-Platform to make a full rest api.

Currently, I'm following the doc, but I don't understand how to get all books of a person by example.

Here I am:

I have Book and Person entities auto generated, I just add a ManyToMany relation between them.

Then I have the following results:

GET api.platform.dev/app_dev.php/

{
    @context: "/app_dev.php/contexts/Entrypoint",
    @id: "/app_dev.php/",
    @type: "Entrypoint",
    person: "/app_dev.php/people",
    book: "/app_dev.php/books"
}

GET api.platform.dev/app_dev.php/people/3

{
    @context: "/app_dev.php/contexts/Person",
    @id: "/app_dev.php/people/3",
    @type: "http://schema.org/Person",
    birthDate: null,
    description: "test",
    gender: "Femme",
    name: "test",
    url: null,
    books: [
        "/app_dev.php/books/1",
        "/app_dev.php/books/4"
    ]
}

Here is my questions, How can I get in the second result an hypermedia to all books of the person, and What is the best option to get all books of a person ?

I have started with create my custom operation:

#services.yml
resource.person.item_operation.custom_get:
    class:   "Dunglas\ApiBundle\Api\Operation\Operation"
    public:  false
    factory:
        - "@api.operation_factory"
        - "createItemOperation"
    arguments:
        - "@resource.person"                  # Resource
        - ["GET"]                             # Methods
        - "/people/{id}/books"                # Path
        - "AppBundle:Person:custom"           # Controller
        - "my_custom_route2"                  # Route name
        - # Context (will be present in Hydra documentation)
            "@type":       "hydra:Operation"
            "hydra:title": "A custom operation"
            "returns":     "xmls:string"

and

// PersonController.php
<?php

namespace AppBundle\Controller;

use Dunglas\ApiBundle\Controller\ResourceController;
use Symfony\Component\HttpFoundation\Request;

class PersonController extends ResourceController
{
    public function customAction(Request $request, $id)
    {
        return parent::getAction($request, $id);
    }
}

result on GET api.platform.dev/app_dev.php/people/3/books is the same of the basic api.platform.dev/app_dev.php/people/3, normal I call the parent.

But now what is the best way to have something like this:

# GET api.platform.dev/app_dev.php/people/3/books
{
    @context: "/app_dev.php/contexts/Book",
    @id: "/app_dev.php/people/3/books",
    @type: "hydra:PagedCollection",
    hydra:totalItems: 2,
    hydra:itemsPerPage: 30,
    hydra:firstPage: "/app_dev.php/people/3/books",
    hydra:lastPage: "/app_dev.php/people/3/books",
    hydra:member: [
        {
            @id: "/app_dev.php/books/1",
            @type: "http://schema.org/Book",
            illustrator: [ ],
            isbn: null,
            numberOfPages: 1230,
            author: [ ],
            datePublished: null,
            description: "Desription",
            genre: null,
            name: "someone",
            publisher: null
        },
        {
            @id: "/app_dev.php/books/2",
            @type: "http://schema.org/Book",
            illustrator: [ ],
            isbn: null,
            numberOfPages: 1230,
            author: [ ],
            datePublished: null,
            description: "Desription",
            genre: null,
            name: "someone",
            publisher: null
        }
    ]
}

And when I get api.platform.dev/app_dev.php/people/3 add this IRI /app_dev.php/people/3/books

Thanks you for the help you could give me.

1 Answer 1

1

Creating sub collections like this is doable but complex with the v1 of API Platform as it requires to create a lot of custom classes (it will be easier with the v2).

What I would suggest is to use the following structure:

GET /books?people=/people/3: retrieve all books owned bu the people 3

It can be done easily using the builtin API Platform search filter.

Then, if you want hypermedia support (btw do you really need it - I mean, is your client able to dereference such hypermedia links?), you need can create a custom Symfony normalizer decorating the Dunglas\ApiBundle\JsonLd\Serializer\ItemNormalizer (service api.json_ld.normalizer.item) provided by API Platform and adding a link to /books?people=/people/3 for the books property.

If you want to still want to follow the road you started, you need to use the Dunglas\ApiBundle\Hydra\Serializer\CollectionNormalizer to normalize your collection in the Hydra format. You can still decorate the ItemNormalizer to point to your custom collection URL.

I hope this help.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.