【问题标题】:Unable to guess how to get a Doctrine无法猜测如何获得教义
【发布时间】:2016-12-16 03:39:12
【问题描述】:

[设置]

  • Symfony 3
  • CalendarEntity 可以是 ChocolateEntity 的父级
  • BoxEntity 是父 WrapperEntity
  • WrapperEntity 可以是 ChocolateEntity 的父级,并且始终是 BoxEntity 的子级
  • ChocolateEntity 只能是 CalendarEntityWrapperEntity 的孩子

[问题]

当我尝试从 CalendarEntityBoxEntity 导航到 chocolate/showchocolate/edit 路由时,我收到以下消息:

无法从请求信息中猜出如何获取Doctrine实例

chocolate/indexchocolate/new 路由运行良好。
直到我在控制器中为CalendarEntity 添加代码之前,每条路由都运行良好。

检查 dev.log 文件给了我这个:

// Route: /calendar/{idCalendar}/chocolate/{idChocolate}/show
request.INFO: Matched route "calendar_chocolate_show". {"route":"calendar_chocolate_show","route_parameters":{"_controller":"AppBundle\\Controller\\ChocolateController::showAction","idCalendar":"1","idChocolate":"3","_route":"calendar_chocolate_show"},"request_uri":"http://sphere.gdn/app_dev.php/calendar/1/chocolate/3/show","method":"GET"} []

// Route: /box/{idBox}/wrapper/{idWrapper}/chocolate/{idChocolate}/show
request.INFO: Matched route "wrapper_chocolate_show". {"route":"wrapper_chocolate_show","route_parameters":{"_controller":"AppBundle\\Controller\\ChocolateController::showAction","idBox":"1","idWrapper":"1","idChocolate":"1","_route":"wrapper_chocolate_show"},"request_uri":"http://sphere.gdn/app_dev.php/box/1/wrapper/1/chocolate/1/show","method":"GET"} []

在我看来,Symfony 对每个请求都有所有需要的参数,并且没有额外的参数。
我不知道如何解决这个问题。

[文件]

实体:

src/AppBundle/Entity/Calendar.php

class Calendar {
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $idCalendar;
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $nameCalendar;
    /**
     * @var
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Chocolate", mappedBy="calendar")
     */
    private $chocolate;
}

src/AppBundle/Entity/Box.php

class Box {
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $idBox;
    /**
     * @var int
     *
     * @ORM\Column(name="parent", type="integer", nullable=true)
     */
    private $parent;
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $nameBox;
    /**
     * @var
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Wrapper", mappedBy="box")
     */
    private $wrapper;
}

src/AppBundle/Entity/Wrapper.php

class Wrapper {
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $idWrapper;
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $nameWrapper;
    /**
     * @var
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Box", inversedBy="wrapper")
     * @ORM\JoinColumn(onDelete="CASCADE", nullable=false)
     */
    private $box;
    /**
     * @var
     *
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\Chocolate", mappedBy="wrapper")
     */
    private $chocolate;
}

src/AppBundle/Entity/Chocolate.php

class Chocolate {
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $idChocolate;
    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $nameChocolate;
    /**
     * @var
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Calendar", inversedBy="chocolate")
     * @ORM\JoinColumn(onDelete="CASCADE", nullable=true)
     */
    private $calendar;
    /**
     * @var
     *
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Wrapper", inversedBy="chocolate")
     * @ORM\JoinColumn(onDelete="CASCADE", nullable=true)
     */
    private $wrapper;
}


路由:

src/AppBundle/Resources/config/calendar.yml

# Calendar
calendar_show:
    path:     /calendar/{idCalendar}/show/
    defaults: { _controller: "AppBundle:Calendar:show" }
    methods:  GET

calendar_edit:
    path:     /calendar/{idCalendar}/edit/
    defaults: { _controller: "AppBundle:Calendar:edit" }
    methods:  [GET, POST]

# Chocolate
calendar_chocolate:
    resource: "@AppBundle/Resources/config/chocolate.yml"
    prefix:   /

src/AppBundle/Resources/config/box.yml

#Box
box_show:
    path:     /box/{idBox}/show/
    defaults: { _controller: "AppBundle:Box:show" }
    methods:  GET

box_edit:
    path:     /box/{idBox}/edit/
    defaults: { _controller: "AppBundle:Box:edit" }
    methods:  [GET, POST]

# Wrapper
box_wrapper:
    resource: "@AppBundle/Resources/config/wrapper.yml"
    prefix:   /

src/AppBundle/Resources/config/wrapper.yml

# Wrapper
wrapper_show:
    path:     /box/{idBox}/wrapper/{idWrapper}/show/
    defaults: { _controller: "AppBundle:Wrapper:show" }
    methods:  GET

wrapper_edit:
    path:     /box/{idBox}/wrapper/{idWrapper}/edit/
    defaults: { _controller: "AppBundle:Wrapper:edit" }
    methods:  [GET, POST]

# Chocolate
wrapper_chocolate:
    resource: "@AppBundle/Resources/config/chocolate.yml"
    prefix:   /

src/AppBundle/Resources/config/chocolate.yml

# Calendar Chocolate
calendar_chocolate_show:
    path:     /calendar/{idCalendar}/chocolate/{idChocolate}/show
    defaults: { _controller: "AppBundle:Chocolate:show" }
    methods:  GET

calendar_chocolate_edit:
    path:     /calendar/{idCalendar}/chocolate/{idChocolate}/edit
    defaults: { _controller: "AppBundle:Chocolate:edit" }
    methods:  [GET, POST]

# Box Chocolate
wrapper_chocolate_show:
    path:     /box/{idBox}/wrapper/{idWrapper}/chocolate/{idChocolate}/show
    defaults: { _controller: "AppBundle:Chocolate:show" }
    methods:  GET

wrapper_chocolate_edit:
    path:     /box/{idBox}/wrapper/{idWrapper}/chocolate/{idChocolate}/edit
    defaults: { _controller: "AppBundle:Chocolate:edit" }
    methods:  [GET, POST]


控制器:

src/AppBundle/Controller/CalendarController.php

class CalendarController extends Controller {
    /**
     * Finds and displays a Calendar entity.
     *
     * @param Calendar $calendar
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function showAction(Calendar $calendar) {
        $deleteForm=$this->createDeleteForm($calendar);

        return $this->render('AppBundle:calendar:show.html.twig', array(
            'calendar'=>$calendar,
            'delete_form'=>$deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing Calendar entity.
     *
     * @param Request $request
     * @param Calendar $calendar
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function editAction(Request $request, Calendar $calendar) {
        $deleteForm=$this->createDeleteForm($calendar);
        $editForm=$this->createForm('AppBundle\Form\CalendarType', $calendar);
        $editForm->handleRequest($request);

        if($editForm->isSubmitted() && $editForm->isValid()) {
            $em=$this->getDoctrine()
                     ->getManager();
            $em->persist($calendar);
            $em->flush();

            return $this->redirectToRoute('calendar_edit', array('idCalendar'=>$calendar->getIdCalendar()));
        }

        return $this->render('AppBundle:calendar:edit.html.twig', array(
            'calendar'=>$calendar,
            'edit_form'=>$editForm->createView(),
            'delete_form'=>$deleteForm->createView(),
        ));
    }
}

src/AppBundle/Controller/BoxController.php

class BoxController extends Controller {
    /**
     * Finds and displays a Box entity.
     *
     * @param Box $box
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function showAction(Box $box) {
        $deleteForm=$this->createDeleteForm($box);

        return $this->render('AppBundle:box:show.html.twig', array(
            'box'=>$box,
            'delete_form'=>$deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing Box entity.
     *
     * @param Request $request
     * @param Box $box
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function editAction(Request $request, Box $box) {
        $deleteForm=$this->createDeleteForm($box);
        $editForm=$this->createForm('AppBundle\Form\BoxType', $box);
        $editForm->handleRequest($request);

        if($editForm->isSubmitted() && $editForm->isValid()) {
            $em=$this->getDoctrine()
                     ->getManager();
            $em->persist($box);
            $em->flush();

            return $this->redirectToRoute('box_edit', array('idBox'=>$box->getIdBox()));
        }

        return $this->render('AppBundle:box:edit.html.twig', array(
            'box'=>$box,
            'edit_form'=>$editForm->createView(),
            'delete_form'=>$deleteForm->createView(),
        ));
    }
}

src/AppBundle/Controller/WrapperController.php

class WrapperController extends Controller {
    /**
     * Finds and displays a Wrapper entity.
     *
     * @param Box $box
     * @param Wrapper $wrapper
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function showAction(Box $box, Wrapper $wrapper) {
        $deleteForm=$this->createDeleteForm($box, $wrapper);

        return $this->render('AppBundle:wrapper:show.html.twig', array(
            'box'=>$box,
            'wrapper'=>$wrapper,
            'delete_form'=>$deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing Wrapper entity.
     *
     * @param Request $request
     * @param Box $box
     * @param Wrapper $wrapper
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function editAction(Request $request, Box $box, Wrapper $wrapper) {
        $deleteForm=$this->createDeleteForm($box, $wrapper);
        $editForm=$this->createForm('AppBundle\Form\WrapperType', $wrapper);
        $editForm->handleRequest($request);

        if($editForm->isSubmitted() && $editForm->isValid()) {
            $em=$this->getDoctrine()
                     ->getManager();
            $em->persist($wrapper);
            $em->flush();
            return $this->redirectToRoute('wrapper_edit', array(
                'idBox'=>$box->getIdBox(),
                'idWrapper'=>$wrapper->getIdWrapper()
            ));
        }

        return $this->render('AppBundle:wrapper:edit.html.twig', array(
            'box'=>$box,
            'wrapper'=>$wrapper,
            'edit_form'=>$editForm->createView(),
            'delete_form'=>$deleteForm->createView(),
        ));
    }
}

src/AppBundle/Controller/ChocolateController.php

class ChocolateController extends Controller {
    /**
     * Finds and displays a Chocolate entity.
     *
     * @param Calendar $calendar
     * @param Box $box
     * @param Wrapper $wrapper
     * @param Chocolate $chocolate
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function showAction(Calendar $calendar=null, Box $box=null, Wrapper $wrapper=null, Chocolate $chocolate) {
        $deleteForm=$this->createDeleteForm($calendar, $box, $wrapper, $chocolate);

        return $this->render('AppBundle:chocolate:show.html.twig', array(
            'calendar'=>$calendar,
            'box'=>$box,
            'wrapper'=>$wrapper,
            'chocolate'=>$chocolate,
            'delete_form'=>$deleteForm->createView(),
        ));
    }

    /**
     * Displays a form to edit an existing Chocolate entity.
     *
     * @param Request $request
     * @param Calendar $calendar
     * @param Box $box
     * @param Wrapper $wrapper
     * @param Chocolate $chocolate
     *
     * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function editAction(Request $request, Calendar $calendar=null, Box $box=null, Wrapper $wrapper=null, Chocolate $chocolate) {
        $deleteForm=$this->createDeleteForm($calendar, $box, $wrapper, $chocolate);
        $editForm=$this->createForm('AppBundle\Form\ChocolateType', $chocolate);
        $editForm->handleRequest($request);

        if($editForm->isSubmitted() && $editForm->isValid()) {
            $em=$this->getDoctrine()
                     ->getManager();
            $em->persist($chocolate);
            $em->flush();
            if($box) {
                return $this->redirectToRoute('wrapper_box_chocolate_edit', array(
                    'idBox'=>$box->getIdBox(),
                    'idWrapper'=>$wrapper->getIdWrapper(),
                    'idChocolate'=>$chocolate->getIdChocolate()
                ));
            } else {
                return $this->redirectToRoute('calendar_chocolate_edit', array(
                    'idCalendar'=>$calendar->getIdCalendar(),
                    'idWrapper'=>$wrapper->getIdWrapper(),
                    'idChocolate'=>$chocolate->getIdChocolate()
                ));
            }
        }

        return $this->render('AppBundle:chocolate:edit.html.twig', array(
            'calendar'=>$calendar,
            'box'=>$box,
            'wrapper'=>$wrapper,
            'chocolate'=>$chocolate,
            'edit_form'=>$editForm->createView(),
            'delete_form'=>$deleteForm->createView(),
        ));
    }
}

【问题讨论】:

  • 已经检查过这个答案,但他的情况和我的情况似乎不同,而且他的解释很草率......无法得到有关问题的真正提示。
  • 你用过@ParamConverter 吗?
  • 是的,就像链接主题中的“建议”。但就像我告诉阿尔文一样,它什么也没做。并且 symfony doc 没有关于当多个实体使用一个公共实体时如何使用它的示例。

标签: doctrine-orm doctrine symfony


【解决方案1】:

由于每个实体都是相关的,因此您无需将额外的参数传递给您的 showAction()editAction()

收回你的代码,showAction() 会变成这样:

public function showAction(Chocolate $chocolate) {
    $deleteForm=$this->createDeleteForm($video);

    return $this->render('AppBundle:chocolate:show.html.twig', array(
        'chocolate'=>$chocolate,
        'delete_form'=>$deleteForm->createView(),
    ));
}

你的editAction() 会变成这样:

public function editAction(Request $request, Chocolate $chocolate) {
    $deleteForm=$this->createDeleteForm($chocolate);
    $editForm=$this->createForm('AppBundle\Form\ChocolateType', $chocolate);
    $editForm->handleRequest($request);

    if($editForm->isSubmitted() && $editForm->isValid()) {
        $em=$this->getDoctrine()
                 ->getManager();
        $em->persist($chocolate);
        $em->flush();
        if($chocolate->getWrapper() !== null) {
            return $this->redirectToRoute('wrapper_chocolate_edit', 

        array(
            'idBox'=>$chocolate->getWrapper()->getBox()->getIdBox(),
            'idWrapper'=>$chocolate->getWrapper()->getIdWrapper(),
            'idChocolate'=>$chocolate->getIdChocolate()
        ));
    } else {
        return $this->redirectToRoute('calendar_chocolate_edit',
            array(
                'idCalendar'=>$chocolate->getCalendar()->getIdCalendar(),
                'idChocolate'=>$chocolate->getIdChocolate()
                ));
            }
        }

        return $this->render('AppBundle:Dashboard/chocolate:edit.html.twig', array(
            'chocolate'=>$chocolate,
            'edit_form'=>$editForm->createView(),
            'delete_form'=>$deleteForm->createView(),
        ));
    }

每个信息都在ChocolateEntity中,你只需要每次获取parent,然后获取需要的参数。

正如您所做的那样,只有showAction()newAction() 需要有参数,这是因为在这两种情况下,您都不会返回特定的ChocolateEntity

public function indexAction(Calendar $calendar=null, Wrapper $wrapper=null)
public function newAction(Request $request, Calendar $calendar=null, Wrapper $wrapper=null)

editAction() 一样,您可以在不通过父母的情况下获得父母。

另请注意,您的树枝会发生一些变化。 例如,当您显示一个实体 (showAction()) 时,“返回列表”链接将根据路线发生变化,然后会给出如下内容:

{% if chocolate.wrapper is not null %}
    <a href="{{ path('wrapper_chocolate_list', { 'idBox': chocolate.wrapper.box.idBox, 'idWrapper': chocolate.wrapper.idWrapper }) }}">Back to the list</a>
{% else %}
    <a href="{{ path('calendar_chocolate_list', { 'idCalendar': chocolate.calendar.idCalendar }) }}">Back to the list</a>
{% endif %}

这样做会提示 Symfony 获取父母数据,即使您只传递 ChocolateEntity 作为参数。其他树枝文件也一样。

希望对你有帮助。

这个话题很好吃,我自己去买巧克力。

【讨论】:

  • 确实解决了我的问题!把它应用到我的项目中,当我在做的时候,谢谢你的详细回复!
【解决方案2】:

所以 Preciel,在 ChocolateController 中尝试:

/**
 * Finds and displays a Chocolate entity.
 *
 * @param Calendar $calendar
 * @param Box $box
 * @param Wrapper $wrapper
 * @param Chocolate $chocolate
 *
 * @return \Symfony\Component\HttpFoundation\Response
 *
 *  @ParamConverter("calendar", class="AppBundle:Calendar")
 *  @ParamConverter("chocolate", class="AppBundle:Chocolate")
 */
public function showAction(Calendar $calendar=null, Box $box=null, Wrapper $wrapper=null, Chocolate $chocolate) {
...

我认为@Vamsi 是正确的。

【讨论】:

  • 我试过这么简单的语法是的,甚至将它扩展到其他两个实体,但没有奏效。 :(
  • 什么不起作用?你能显示这条路线的日志吗:http://sphere.gdn/app_dev.php/calendar/1/chocolate/3/show
  • 您好 Preciel。我不打算花太多时间在这上面。大多数用户都很忙,这就是为什么我们喜欢好的(措辞好的)问题。您可以使用pastebin 发布日志吗?
  • 哦,我不是那个意思。就像你猜到的那样,一切都被重命名了。所以我认为能够在开发端访问我的网站会更好地帮助你,仅此而已。这是我访问路径时得到的行。 pastebin.com/y9LYNj8m
猜你喜欢
  • 2015-12-14
  • 2016-05-03
  • 1970-01-01
  • 2017-06-25
  • 2013-12-23
  • 1970-01-01
  • 2018-09-06
  • 2017-04-21
  • 2016-07-01
相关资源
最近更新 更多