copndz
copndz

Reputation: 1104

Unable to guess how to get a Doctrine instance from the request information

I've got this "500 Internal Server Error - LogicException: Unable to guess how to get a Doctrine instance from the request information".

Here is my controller's action definition:

/**
 * @Route("/gatherplayer/{player_name}/{gather_id}")
 * @Template()
 */
public function createAction(Player $player, Gather $gather)
{
  // ...
}

And it doesn't work, probably because Doctrine 2 can not "guess"... So how do I make Doctrine 2 guess, and well?

Upvotes: 23

Views: 56652

Answers (6)

Dylan KAS
Dylan KAS

Reputation: 5663

As of symfony 6.2, SensioFrameworkExtraBundle is deprecated. Features such as annotation routing, param convertion are now integrated in Symfony directly.

Note that ParamConverter are now called ValueResolver

You need to be in Symfony > 6.2, PHP >= 8.1 and DoctrineBundle >= 2.7.1

It is now easy to map an ID to an entity :

#[Route('/post/{id}')]
public function show(Post $post): Response
{
    //  $post is a Post entity
}

This behavior is activated by default and can be disabled with doctrine.orm.controller_resolver.auto_mapping to false.

If you are fetching your object differently, by another property for example, instead of using the ParamConverter from SensioFrameworkExtraBundle, you can now use the #[MapEntity] php attribute.

Example from the link posted above replacing a ParamConverter with MapEntity when using a slug to find your entity:

#[ParamConverter('post', options: ['mapping' => ['postSlug' => 'slug']])]
public function addComment(Request $request, Post $post): Response

Turn into:

use Symfony\Bridge\Doctrine\Attribute\MapEntity;
public function addComment(
    Request $request,
    #[MapEntity(mapping: ['postSlug' => 'slug'])] Post $post
): Response

MapEntity has plenty other options that can be useful.

See the documentation about Automatically Fetching Objects (EntityValueResolver)

Upvotes: 0

The parameters on the signature of the @Route annotation must match the entities fields, so that Doctrine makes automatically the convertion.

Otherwise you need to do the convertion manually by using the annotation @ParamConverter as it's mentionned on the other responses.

Upvotes: 2

Azr
Azr

Reputation: 1143

The Doctrine doesn't know how to use request parameters in order to query entities specified in the function's signature.

You will need to help it by specifying some mapping information:

/**
  * @Route("/gatherplayer/{player_name}/{gather_id}")
  *
  * @ParamConverter("player", options={"mapping": {"player_name" : "name"}})
  * @ParamConverter("gather", options={"mapping": {"gather_id"   : "id"}})
  *
  * @Template()
  */
public function createAction(Player $player, Gather $gather)
{
  // ...
}

Upvotes: 38

copndz
copndz

Reputation: 1104

/**
 * @Route("/gatherplayer/{name}/{id}")
 * @Template()
 */
public function createAction(Player $player, Gather $gather)

I didn't find any help in paramconverter's (poor?) documentation, since it doesn't describe how it works, how it guesses with more than one parameters and stuff. Plus I'm not sure it's needed since what I just wrote works properly.

My mystake was not to use the name of my attributs so doctrine couldn't guess right. I changed {player_name} to {name} and {gather_id} to {id}.

Then I changed the names of my id in their entities from "id" to "id_gather" and "id_player" so I'm now able to do that :

/**
 * @Route("/gatherplayer/{id_player}/{id_gather}")
 * @Template()
 */
public function createAction(Player $player, Gather $gather)

which is a lot more effective than

 * @Route("/gatherplayer/{id}/{id}")

Now I'm wondering how I can make this work

 /**
  * @Route("/gatherplayer/{player}/{gather}")
  * @Template()
  */
 public function deleteAction(Gather_Player $gather_player)

Upvotes: 12

Lhassan Baazzi
Lhassan Baazzi

Reputation: 1150

try this:

/**
 * @Route("/gatherplayer/{player_name}/{gather_id}")
 * @ParamConverter("player", class="YourBundle:Player")
 * @ParamConverter("gather", class="YourBundle:Gather")
 * @Template()
 */
public function createAction(Player $player, Gather $gather)

Upvotes: 5

ftassi
ftassi

Reputation: 335

@1ed is right, you should define a @paramConverter in order to get a Player instance or a Gather instance.

Upvotes: 0

Related Questions