core: Unable to generate an IRI

Hi!

I’m trying to build a custom collection.

AppBundle/Entity:

/**
 * @ApiResource(
 *     collectionOperations={
 *         "get"={"method"="GET"},
 *         "event"={"route_name"="place_event"}
 *     },
 *     itemOperations={
 *         "get"={"method"="GET"}
 *     },
 *     attributes={
 *         "normalization_context"={"groups"={"place"}}
 *     }
 * )
 */
class LocalBusiness
{
// ...
}

AppBundle/Action:

   /**
     * @Route(
     *     name="place_event",
     *     path="/local_businesses/{id}/events",
     *     defaults={"_api_resource_class"=LocalBusiness::class, "_api_collection_operation_name"="event"}
     * )
     * @Method("GET")
     */
    public function __invoke()
    {
        return array('test', 'test');
    }

If I try to run this endpoint in Postman, it throws the “Unable to generate an IRI” exception.

Is there anything I can do?

Thank you so much.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 26 (3 by maintainers)

Most upvoted comments

Sorry! No problem is solved 👍

Sorry! No problem is solved 👍

very professional statement inside an issue tracker

@jorgeluisacostaalonso I don’t remember, but I think that was related to the “null id” of the entity

I had this problem because the first ‘collectionOperation’ of the entity was custom with a {slug} param. To make sure Api Platform is able to properly generate the IRI you must add a default GET operation in your collectionOperations for the entity.

You should be able to check if this is your case when debugging IriConverter::getIriFromResourceClass(), behaviour explained here.

Not working

* @ApiResource(
 *      normalizationContext={"groups"={"issueSubcategory:read"}},
 *      denormalizationContext={"groups"={"issueSubcategory:write"}},
 *      collectionOperations={
 *          "subcategoriesByCategory"={
 *              "method"="GET",
 *              "path"="/issueCategories/{id}/issueSubcategories",
 *              "controller"=IssueSubcategoriesByCategoryController::class,
 *              "read"=false,
 *              "openapi_context"={"summary"="Retrieve all issue subcategories by category"},
 *              "defaults"={"_api_receive"=false}
 *          },
 *      },
 *      itemOperations={
 *          "get"
 *      }
 * )

Working

* @ApiResource(
 *      normalizationContext={"groups"={"issueSubcategory:read"}},
 *      denormalizationContext={"groups"={"issueSubcategory:write"}},
 *      collectionOperations={
 *          "get",
 *          "subcategoriesByCategory"={
 *              "method"="GET",
 *              "path"="/issueCategories/{id}/issueSubcategories",
 *              "controller"=IssueSubcategoriesByCategoryController::class,
 *              "read"=false,
 *              "openapi_context"={"summary"="Retrieve all issue subcategories by category"},
 *              "defaults"={"_api_receive"=false}
 *          },
 *      },
 *      itemOperations={
 *          "get"
 *      }
 * )

Had a similar problem, turned out the fields of my resource entity were set to private and since I hadn’t created getters and setters at that point the API was unable to generate a route for that entity.

I just had the problem for a second time, this time related to custom collection operations.

In my routing definitions, the route for my custom collection operation was positioned before the main API route. For some reason, when the system tries to generate the route for an API resource, it seems to look for collection operations in the route definitions and return the first match. In my case, this was the custom collection operation. My collection operation route also used a mandatory parameter, so the system ultimately fails because it can’t find the mandatory parameter. Hopefully it’s an understandable story and it clears some things up for others.

So in short, this:

api_custom_route_name:
    path: '/api/orders/{mandatory}'
    methods:  ['GET']
    defaults:
        _controller: 'Application\Action\CustomAction'
        _api_resource_class: 'Application\Entity\Order'
        _api_collection_operation_name: 'custom'
        
api:
    resource: '.'
    type:     'api_platform'
    prefix:   '/api'

should become this:

api:
    resource: '.'
    type:     'api_platform'
    prefix:   '/api'

api_custom_route_name:
    path: '/api/orders/{mandatory}'
    methods:  ['GET']
    defaults:
        _controller: 'Application\Action\CustomAction'
        _api_resource_class: 'Application\Entity\Order'
        _api_collection_operation_name: 'custom'

I had the similar problem, my persist method in DataPersister was look like: image

I fixed it by call persist and flush to doctrine, after this this is looking like: image

I have the same issue, reason was I forgot to create getter for id 😉 maybe I’ll save some time for someone else 😃

same issue, but nothing mentioned here helped.

As a test I was creating objects with new SomeEntity($id) in an item provider and got the error which was caused by the missing constructor in the entity. So after adding the constructor to SomeEntity it did work.

function __construct($id) {
    $this->id = $id;
}

I am using a non-doctrine Entity with custom provider.