【问题标题】:Unable to guess how to get a Doctrine instance无法猜测如何获取 Doctrine 实例
【发布时间】:2016-05-03 09:19:18
【问题描述】:

我已经完成了将我的项目从 Symfony 2.8 更新到 Symfony 3 的过程,现在我正在重新设计我的一个控制器,但遇到了一些问题。

我有一个子实体和控制器。控制器有一个基本路由

/**
* Child controller.
*
* @Route("/profile/{parentName}/{childName}")
*/

有一个动作

/**
 * 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(),
    );
}

但是我不希望页面 URL 是 domain.com/parentname/childname/id 我希望它是 domain.com/parentname/childname

在 2.8 中,我的控制器是

/**
* 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(),
    );
}

它按我的意愿工作。

但是,如果在我更新的控制器中,我将 showAction 上的路由注释修改为

/**
* @Route("/", name="child_show")
* @Method("GET")
* @Template()
*/

我收到一个错误无法猜测如何从请求信息中获取 Doctrine 实例。 我猜是因为需要 Id 来获取正确的 Child 实例?但是 Child 实体中的 childName ($name) 也是唯一的。

我对此有点坚持。谁能告诉我我做错了什么?我希望能够为不包含 ID 但使用孩子的姓名返回所需信息的孩子个人资料页面提供路线。

针对一些 cmets / 问题进行更新 - 以下是我的子实体

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;
}
}

并将showAction修改为

/**
* 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(),
    );
}

但我现在得到一个错误 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 

【问题讨论】:

  • parentNamechildName 是用于匹配和获取实体的属性的确切名称吗?如果没有,您应该使用 ParamConverter 注释。
  • @Sogara 不,他们不是,我稍后再检查一下,谢谢!在子实体上定义的父级 *@ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="id") * @ORM\JoinColumn(onDelete="CASCADE") */ private $parent;但是我认为我在这个版本中也有其他更正,因为目前我可以在 URL 中为 parentName 设置任何值(domain.com/john/sam/56 和 domain.com/mary/sam/56 都可以)等等只要孩子 ID 在 url 中,就会返回孩子。
  • @Sogara 我已经更新了我的问题以使用相同的属性,但我现在得到一个 AppBundle\Entity\Child object not found 错误。

标签: php doctrine-orm doctrine symfony


【解决方案1】:

@丹·科斯蒂内尔

我收到了同样的错误信息,但我想,与你的方式有点不同。

“无法为命名路由“users_delete”生成 URL,因为这样的路由不存在”

我忘记在 routing.yml 中的路由中添加请求的 {variable}

users_delete:
    path:     /{id}/modifier
    defaults: { _controller: ReservationBundle:Users:modifier }

这就是为什么我的控制器无法访问 $request 变量中预期的信息的原因:

public function modifierAction(Request $request, Users $user) {}

但这是你的回答让我走上了正轨:

@Route 中的那个 {name} 改变了一切。我的意思是这导致 错误。所以我需要确保我应该而不是 {name} 在我的锚元素的“标题”部分中有 {title} ({ 'title': article.title|lower })。

【讨论】:

    【解决方案2】:

    我收到了同样的错误信息,但我想,情况与你的情况有点不同。

    我需要在其自己的树枝模板中呈现特定文章。所以我有:

    <a href="{{ path('article_show', { 'title': article.title|lower }) }}" class="pull-right">Read More</a>,其中'title' 是表中列的名称。

    但在我的控制器类中,我有:

    /**
     * @Route("/article/{name}", name="article_show")
     * @Method("GET")
     */
    public function showAction(Article $article)
    {
        return $this->render('AppBundle:Article:show.html.twig', ['article'=>$article]);
    }
    

    @Route 中的 {name} 改变了一切。我的意思是这导致了错误。所以我需要确保在我的锚元素 ({ 'title': article.title|lower }) 的 'title' 部分中,我应该拥有 {title} 而不是 {name}

    【讨论】:

      【解决方案3】:

      找不到实体,因为 Doctrine 找不到名称为 {name} 和 parentName parentName 的 Child...这似乎是合法的,因为 Child 实体中不存在 parentName。

      两种解决方案:

      1 - 从未尝试过,但可能有效:在 Child 中创建 getParentName() 并使其成为 return $this->parent->getName()

      2 - 在控制器操作的顶部添加 ParamConverter 注释:

      /**
       * 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)
      

      这样,转换器在尝试检索您的子实体时只会考虑参数“名称”...(顺便说一句,这真的是您想要的吗?) 不要忘记在控制器中use ParamConverter。

      【讨论】:

      • 感谢您 - 完美运行!实际上,我想在检索配置文件时考虑 parentName 和 childName(现在的名称),但我想我可以使用其他 ParamConverters 进行排序。一个全新的功能来了解:)。将其标记为答案。再次感谢。
      • 谢谢! :) 我不完全确定您可以使用 ParamConverter 来考虑关系中的字段,但请尝试一下,否则您可以在 Controller 中手动执行此操作。祝你好运!
      【解决方案4】:

      如果您有唯一字段,则应在实体定义中将它们标记为唯一:

      the @column annotation:

      /**
       * @Column(type="string", length=32, unique=true, nullable=false)
       */
      protected $name;
      

      或者other unique constraints

      /**
       * @entity
       * @Table(name="child", uniqueConstraints{   
       *     @UniqueConstraint(name="name_something_unique", columns = {"name", "something"})
       * })
       */
      

      如果您为name 添加@column 唯一约束,那么您的findOneByName 可能会按预期工作。

      你现在也可以让它像这样工作:

      $childs = $em->getRepository('AppBundle:Child')->findBy( array('name' => $childName ));
      

      然后你得到一个Collection,如果你确定它是唯一的,你可以简单地得到first元素,如果集合不是empty...

      if( ! $childs->isEmpty() ){
      
          $first = $childs->first();
      
      }
      

      【讨论】:

      • 谢谢@Wilt - 今天晚些时候我会好好看看。我的子实体 @ORM\Column(name="name", type="string", length=255 确实有唯一的名称,但需要查看您的其他一些建议
      • 我已经发布了我的子实体,并且似乎具有您所描述的正确注释,但我收到了 AppBundle\Entity\Child object not found 错误。你有什么想法吗?
      • @StuartBrown 是否在正确的文件夹中?确保删除类顶部和注释之间的所有空白...
      猜你喜欢
      • 2012-04-01
      • 2019-08-05
      • 2021-06-27
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      • 2021-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多