Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The total number of joined relations has exceeded the specified maximum #1910

Closed
Aerendir opened this issue Apr 30, 2018 · 6 comments
Closed

Comments

@Aerendir
Copy link
Contributor

Aerendir commented Apr 30, 2018

I have two entities, one representing a Todo

// Todo entity
/**
 * @ORM\Table(name="coo_app_todos")
 * @ORM\Entity()
 * @ApiResource(
 *     attributes={
 *        "normalization_context"={"groups"={"todo"}}
 *     },
 *     itemOperations={
 *          "get",
 *          "put"={"normalization_context"={"groups"={"put"}}}
 *     }
 * )
 */
class Todo
{
    use TimestampableEntity;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @Groups({"todoList", "todo"})
     */
    private $id;

    /**
     * @var TodoList
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\TodoList", inversedBy="todos")
     * @ORM\JoinColumn(name="toto_list", referencedColumnName="id")
     * @Groups({"todo", "put"})
     */
    private $todoList;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     * @Groups({"todoList", "todo", "put"})
     */
    private $name;

    ...

}

and one representing a TodoList:

// TodoList
/**
 * @ORM\Table(name="coo_app_todo_lists")
 * @ORM\Entity()
 *
 * This makes possible to return also the todos associated to the fetched TodoList.
 * @ApiResource(attributes={
 *     "normalization_context"={"groups"={"todoList"}}
 * })
 */
class TodoList
{

    ...

    /**
     * @var Collection
     *
     * @ORM\OneToMany(targetEntity="App\Entity\Todo", mappedBy="todoList")
     * @ORM\OrderBy({"opened" = "DESC"})
     * @ApiSubresource()
     * @Groups("todoList")
     */
    private $todos;

    ...

}

A Todo is obviously associated to a TodoList and I need that when I fetch a Todo, I get also some details of the TodoList.

But this configuration doesn't permit me to create new Todos as I receive this error:

The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary, or use the "max_depth" option of the Symfony serializer.

I'm trying with a payload like this:

{
    "todoList": "/api/todo_lists/1",
    "name": "Vediamo che succede"
}

Nothing complex: just the name of the Todo and the TodoList in which it is.

I've tried to add "put"={"normalization_context"={"groups"={"put"}}} to the itemOperations but this didn't solved my problem.

Any ideas of how I can solve this problem?

I need that the TodoList is embedded in the response I receive for a single Todo and, obviously, I want to be able to also create new Todos.

Thank you!

PS

The api documentation is telling me that the payload should be something like this:

{
  "todoList": {
    "account": "string",
    "name": "string",
    "createdAt": "2018-04-30T14:24:44.463Z",
    "updatedAt": "2018-04-30T14:24:44.463Z"
  },
  "name": "string",
  "description": "string",
  "opened": true,
  "createdAt": "2018-04-30T14:24:44.463Z",
  "updatedAt": "2018-04-30T14:24:44.463Z"
}

So I think that there is something wrong with the configuration of the embedding...

@soyuka
Copy link
Member

soyuka commented Apr 30, 2018

There's a relation joining recursivity.
Two solutions:

  1. Disable eager loading ( https://api-platform.com/docs/core/performance#eager-loading ) The total number of joined #876 (comment)
  2. Use @MaxDepth with enable_max_depth: true
@ApiResource(attributes={"normalization_context": {"groups"={"todolist"}, "enable_max_depth"=true}})

@Simperfit Simperfit changed the title The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary, or use the "max_depth" option of the Symfony serializer. The total number of joined relations has exceeded the specified maximum Apr 30, 2018
@Aerendir
Copy link
Contributor Author

Aerendir commented Apr 30, 2018

@soyuka , thank you for your fast reply!

Can you provide me with an example, please?

I've tried to use enable_max_depth and the annotation @MaxDepth as shown in the Symfony's Serializer doc, but the problem isn't solved, so maybe I'm continuing to configure it wrong...

I've enabled the annotations for Serializer in framework and set the @MaxDepth(1) annotation on properties Todo::todoList and TodoList::todos but this seems to not solve the problem.

@Aerendir
Copy link
Contributor Author

Aerendir commented May 3, 2018

Ok, I'm doing other tests, but without success.

TEST 1: Disable eagerLoading on a ApiResource basis

First, I tried to disable the eagerLoading this way:

// Todo entity
/**
 * @ORM\Table(name="coo_app_todos")
 * @ORM\Entity()
 * @ApiResource(attributes={
 *     "fetchEager": false,
 *     "normalization_context"={"groups"={"todo"}}
 * })
 */
class Todo
{
    ...
}

and

// TodoList entity
/**
 * @ORM\Table(name="coo_app_todo_lists")
 * @ORM\Entity()
 *
 * This makes possible to return also the todos associated to the fetched TodoList.
 * @ApiResource(attributes={
 *     "fetchEager": false,
 *     "normalization_context"={"groups"={"todoList"}}
 * })
 */
class TodoList
{
    ...
}

FAILED: The error is still there.

TEST 2: Disable eager loading for all resources

As suggested by @dunglas in #876 (comment) and described in the documentation here, I added this to my config/packages/api_platform.yaml config file:

api_platform:
    mapping:
        paths: ['%kernel.project_dir%/src/Entity']
    eager_loading:
      force_eager: false

SOLVED: This solved the problem, but opened another one.

THE CURRENT PROBLEM

Using force_eager: false now I can create new todos but I suspect this will impact performances.

So, my question is: is this behavior intended? Is it possible that if one uses @Groups (s)he incurs in those problems?

TEST 3: force_eager at @ApiResource level

As suggested by @soyuka in api-platform/api-platform#187 (comment) (and also in a previous comment in this issue too ), I did this:

// TodoList entity
/**
 * @ORM\Table(name="coo_app_todo_lists")
 * @ORM\Entity()
 *
 * This makes possible to return also the todos associated to the fetched TodoList.
 * @ApiResource(attributes={
 *     "force_eager"=false, // Instead of "fetchEager": false,
 *     "normalization_context"={"groups"={"todoList"}}
 * })
 */
class TodoList
{
    ...
}

This worked too!

CONCLUSIONS

So, my suggestion is to create a troubleshooting section in the documentation where this issue is addressed and the solutions I tried here are better described: I spent a lot of time figuring out how to solve the issue!

Anyway, thank you @soyuka and @dunglas for the suggestione you leave in the issues: reading with more calm and deeper, I was able to finally solve the issue!

@Aerendir Aerendir closed this as completed May 3, 2018
@nckenn
Copy link

nckenn commented Jul 5, 2018

How did you solve this issue? can you give me idea? :)

@br750
Copy link

br750 commented Sep 28, 2018

work for me 👍
`@ApiResource(attributes={

  • "force_eager"=false,
    
  • "normalization_context"={"groups"={"readCO"},"enable_max_depth"=true},
    
  • "denormalization_context"={"groups"={"writeCO"},"enable_max_depth"=true}
    
  • })`

@br750
Copy link

br750 commented Sep 28, 2018

work without "force_eager"=false TOO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants