Reputation: 987
I have been through the process of updating my project from Symfony 2.8 to Symfony 3 and am now reworking one of my controllers but am having some trouble.
I have a Child entity and controller. The controller has a base route
/**
* Child controller.
*
* @Route("/profile/{parentName}/{childName}")
*/
with an action
/**
* Finds and displays a Child entity.
*
* @Route("/{id}", name="child_show")
* @Method("GET")
* @Template()
*/
public function showAction(Child $child)
{
$deleteForm = $this->createDeleteForm($child);
return array(
'child' => $child,
'delete_form' => $deleteForm->createView(),
);
}
However I don't want the page URL to be domain.com/parentname/childname/id I want it to be domain.com/parentname/childname
In 2.8 my controller was
/**
* Child controller.
*
* @Route("/profile/{parentName}/{childName}")
*/
/**
* Finds and displays a Child entity.
*
* @Route("/", name="child_show")
* @Method("GET")
* @Template()
*/
public function showAction($childName)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('AppBundle:Child')->findOneByName($childName);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Child entity.');
}
$deleteForm = $this->createDeleteForm($childName);
return array(
'entity' => $entity,
'delete_form' => $deleteForm->createView(),
);
}
and it worked as I wanted.
However if in my updated controller I modify the route annotation on showAction to
/**
* @Route("/", name="child_show")
* @Method("GET")
* @Template()
*/
I get an error Unable to guess how to get a Doctrine instance from the request information. I guess because the Id is needed to get the correct instance of Child? However childName ($name) in the Child entity is also unique.
I'm a bit stuck with this. Can anyone advise what I am doing wrong? I want to be able to have a route for the child profile page that doesn't contain the ID but uses the child's name to return the info required.
Update in response to some comments / questions - below is my Child entity
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use AppBundle\Entity\User;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* Child
*
* @ORM\Table()
* @ORM\Entity(repositoryClass="AppBundle\Entity\ChildRepository")
* @UniqueEntity("name")
*/
class Child
{
/**
* @var integer
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/*
* Todo - figure out how to use a date type for dateofbirth below and as well in users.yml fixtures file
*/
/**
* @var \DateTime
*
* @ORM\Column(name="date_of_birth", type="datetime")
*/
private $dateOfBirth;
//todo find ot why the parent variable here and Id variable in AppBundle:User are not mapped correctly
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="id")
* @ORM\JoinColumn(onDelete="CASCADE")
*/
private $parent;
/**
* @return User
*/
public function getParent()
{
return $this->parent;
}
/**
* @param User $parent
*/
public function setParent(User $parent)
{
$this->parent = $parent;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Child
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Set dateOfBirth
*
* @param \DateTime $dateOfBirth
*
* @return Child
*/
public function setDateOfBirth($dateOfBirth)
{
$this->dateOfBirth = $dateOfBirth;
return $this;
}
/**
* Get dateOfBirth
*
* @return \DateTime
*/
public function getDateOfBirth()
{
return $this->dateOfBirth;
}
}
and modified the showAction to
/**
* Child controller.
*
* @Route("/profile/{parentName}/{name}")
*/
/**
* Finds and displays a Child entity.
*
* @Route("/", name="child_show")
* @Method("GET")
* @Template()
*/
public function showAction(Child $name)
{
$deleteForm = $this->createDeleteForm($name);
return array(
'child' => $name,
'delete_form' => $deleteForm->createView(),
);
}
but I now get an error AppBundle\Entity\Child object not found.
ERROR - Uncaught PHP Exception
Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "AppBundle\Entity\Child object not found." at /Library/WebServer/Documents/story-project/app/cache/dev/classes.php line 7183
Upvotes: 1
Views: 8865
Reputation: 1
@Dan Costinel
I got the same error message, but I guess, in a little bit different way than yours.
"Unable to generate a URL for the named route "users_delete" as such route does not exist"
I had forgotten to add the requested {variable} in the route in the routing.yml
users_delete:
path: /{id}/modifier
defaults: { _controller: ReservationBundle:Users:modifier }
Thats why my controller couldn't access the information expected in the $request variable:
public function modifierAction(Request $request, Users $user) {}
But that's your anwer that put me in the right track:
That {name} in the @Route changed everything. I mean that was causing the error. So I needed to make sure that instead of {name} I should've have {title} as in the 'title' part of my anchor element ({ 'title': article.title|lower }).
Upvotes: 0
Reputation: 1736
I got the same error message, but I guess, in a bit different situation than yours.
I needed to render a particular article in its own twig template. So I had:
<a href="{{ path('article_show', { 'title': article.title|lower }) }}" class="pull-right">Read More</a>
, where 'title'
was the name of a column in a table.
But in my controller class I had:
/**
* @Route("/article/{name}", name="article_show")
* @Method("GET")
*/
public function showAction(Article $article)
{
return $this->render('AppBundle:Article:show.html.twig', ['article'=>$article]);
}
That {name}
in the @Route
changed everything. I mean that was causing the error. So I needed to make sure that instead of {name}
I should've have {title}
as in the 'title'
part of my anchor element ({ 'title': article.title|lower }
).
Upvotes: 0
Reputation: 2588
The entity is not found, because Doctrine can't find a Child with name {name}
and parentName parentName
... Which seems legit, since parentName does not exist in the Child entity.
Two solutions :
1 - Never tried, but might work : create getParentName() in Child and make it return $this->parent->getName()
2 - Add a ParamConverter annotation on the top of your Controller Action:
/**
* Finds and displays a Child entity.
*
* @Route("/", name="child_show")
* @Method("GET")
* @Template()
* @ParamConverter("child", class="AppBundle:Child", options={"name" = "name"})
*/
public function showAction(Child $child)
This way, the Converter will only consider the argument "name" when attempting to retrieve your Child entity... (is that really what you want by the way?)
Don't forget to use
ParamConverter in your Controller.
Upvotes: 1
Reputation: 44316
If you have unique fields you should mark them as unique in your entity definitions:
/**
* @Column(type="string", length=32, unique=true, nullable=false)
*/
protected $name;
Or for other unique constraints:
/**
* @entity
* @Table(name="child", uniqueConstraints{
* @UniqueConstraint(name="name_something_unique", columns = {"name", "something"})
* })
*/
If you add the @column
unique constraint for name
then your findOneByName
will probably work as expected.
You can for now also make it work like this:
$childs = $em->getRepository('AppBundle:Child')->findBy( array('name' => $childName ));
Then you get a Collection
and if you are sure it is unique you can simply get the first element if the collection is not empty...
if( ! $childs->isEmpty() ){
$first = $childs->first();
}
Upvotes: 0