Symfony 4 Collections形式错误:无法猜测

时间:2018-08-13 18:13:52

标签: php symfony symfony4

我根据http://symfony.com/doc/current/form/form_collections.html文档采取了行动,我需要添加一个公共页面来编辑一个实体的所有记录,并且还建议使用“表单集合”。现在出现了 add use ORM 之类的错误,例如“ ERROR”等。 Unable to guess how to get a Doctrine instance from the request information for parameter "abilityHolder". Google什么也没说,它只显示symfony2的旧信息,而我使用flex,下面将附加与我的文件有关的文件任务

src / Ability.php -我获取和编写能力的主要实体

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\AbilityRepository")
 * @ORM\Table(name="Ability")
 */
class Ability
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="integer", name="idItem")
     */
    private $idItem;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $code;

    /**
     * @ORM\Column(type="float", name="reloadTime", nullable=true)
     */
    private $reloadTime;

    /**
     * @ORM\Column(type="float", name="durationTime", nullable=true)
     */
    private $durationTime;

    /**
     * @ORM\Column(type="integer", name="idAbilityType")
     */
    private $idAbilityType;

    /**
     * @ORM\Column(type="datetime", nullable=true, name="dateCreated")
     */
    private $dateCreated;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $author;

    /**
     * @ORM\Column(type="datetime", nullable=true, name="dateChange")
     */
    private $dateChange;

    /**
     * @ORM\Column(type="string", length=255, nullable=true, name="lastAuthor")
     */
    private $lastAuthor;

    public function getId()
    {
        return $this->id;
    }

    public function setId(?int $id): self
    {
        $this->id = $id;

        return $this;
    }

    public function getIdItem(): ?int
    {
        return $this->idItem;
    }

    public function setIdItem(int $idItem): self
    {
        $this->idItem = $idItem;

        return $this;
    }

    public function getCode(): ?string
    {
        return $this->code;
    }

    public function setCode(?string $code): self
    {
        $this->code = $code;

        return $this;
    }

    public function getReloadTime(): ?float
    {
        return $this->reloadTime;
    }

    public function setReloadTime(?float $reloadTime): self
    {
        $this->reloadTime = $reloadTime;

        return $this;
    }

    public function getDurationTime(): ?float
    {
        return $this->durationTime;
    }

    public function setDurationTime(?float $durationTime): self
    {
        $this->durationTime = $durationTime;

        return $this;
    }

    public function getDateCreated(): ?\DateTimeInterface
    {
        return $this->dateCreated;
    }

    public function setDateCreated(\DateTimeInterface $dateCreated): self
    {
        $this->dateCreated = $dateCreated;

        return $this;
    }

    public function getAuthor(): ?string
    {
        return $this->author;
    }

    public function setAuthor(string $author): self
    {
        $this->author = $author;

        return $this;
    }

    public function getDateChange(): ?\DateTimeInterface
    {
        return $this->dateChange;
    }

    public function setDateChange(\DateTimeInterface $dateChange): self
    {
        $this->dateChange = $dateChange;

        return $this;
    }

    public function getLastAuthor(): ?string
    {
        return $this->lastAuthor;
    }

    public function setLastAuthor(string $lastAuthor): self
    {
        $this->lastAuthor = $lastAuthor;

        return $this;
    }

    public function getIdAbilityType(): ?int
    {
        return $this->idAbilityType;
    }

    public function setIdAbilityType(int $idAbilityType): self
    {
        $this->idAbilityType = $idAbilityType;

        return $this;
    }
}

src / AbilityHolder.php -集合表单实体

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="AbilityHolder")
 */

class AbilityHolder
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    protected $abilitys;

    public function __construct()
    {
        $this->abilitys = new ArrayCollection();
    }

    public function getAbilitys()
    {
        return $this->abilitys;
    }

    public function getId()
    {
        return $this->id;
    }
}

来自Ability的Form / AbilityType.php 表单

<?php

namespace App\Form;

use App\Entity\Ability;
use App\Entity\Item;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use App\Repository\AbilityTypeRepository;
use App\Repository\ItemRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

class AbilityType extends AbstractType
{
    protected $abilityTypeRepository;
    protected $itemRepository;

    public function __construct(AbilityTypeRepository $abilityTypeRepository, ItemRepository $itemRepository){
        $this->abilityTypeRepository = $abilityTypeRepository;
        $this->itemRepository = $itemRepository;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $abilitys = $this->abilityTypeRepository->findAll();
        $items = $this->itemRepository->findAll();
        foreach ($abilitys as $ability) {
            $abilityCode[] = $ability->getCode();
            $abilityId[] = $ability->getId();
        }
        foreach ($items as $item) {
            $itemCode[] = $item->getCode();
            $itemId[] = $item->getId();
        }
        $abilityCodeId = array_combine($abilityCode, $abilityId); //склеивание ассоциативного массива из двух массивов
        $itemCodeId = array_combine($itemCode, $itemId); //склеивание ассоциативного массива из двух массивов
        ksort($abilityCodeId);
        ksort($itemCodeId);

        $builder
            ->add('idItem', ChoiceType::class, array( 'choices'  => $itemCodeId ))
            //->add('idItem', EntityType::class, ['class' => Item::class,'choice_label' => 'code','choice_value' => 'id',])
            ->add('code')
            ->add('reloadTime')
            ->add('durationTime')
            ->add('idAbilityType', ChoiceType::class, array( 'choices'  => $abilityCodeId ))
            // ->add('dateCreated',DateType::class)
            // ->add('author')
            // ->add('dateChange',DateType::class)
            // ->add('lastAuthor')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Ability::class,
        ]);
    }
}

Form / AbilityHolderType.php -来自Ability的表单

<?php

namespace App\Form;

use App\Entity\AbilityHolder;
use App\Form\AbilityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;

class AbilityHolderType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
        ->add('abilitys', CollectionType::class, array(
            'entry_type' => AbilityType::class,
            'entry_options' => array('label' => false),
            'allow_add' => true,
        ))
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => AbilityHolder::class,
        ]);
    }
}

Controller / AbilityHolderController.php -来自AbilityHolder-collections表单的表单

<?php
namespace App\Controller;

use App\Entity\AbilityHolder;
use App\Entity\Ability;
use App\Form\AbilityHolderType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Doctrine\Common\Collections\ArrayCollection;
use App\Controller\EntityManagerInterface;
use App\Repository\AbilityRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;


/**
 * @Route("/ability-holder")
 * @ParamConverter (name ="abilityHolder", Class ="App\Entity\AbilityHolder") 
 */
class AbilityHolderController extends Controller
{

    /**
     * @Route("/edit", name="ability_holder_edit", methods="GET|POST")
     */
    public function edit(Request $request, AbilityHolder $abilityHolder)
    {
        $entityManager = $this->getDoctrine()->getManager();

        $originalAbilitys = new ArrayCollection();

        // Create an ArrayCollection of the current Tag objects in the database
        foreach ($abilityHolder->getAbilitys() as $ability) {
            $originalAbilitys->add($ability);
        }

        $form = $this->createForm(AbilityHolderType::class, $abilityHolder);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // remove the relationship between the tag and the Task
            foreach ($originalAbilitys as $ability) {
                if (false === $abilityHolder->getAbilitys()->contains($ability)) {
                    // remove the Task from the Tag
                    $tag->getTasks()->removeElement($abilityHolder);

                    // if it was a many-to-one relationship, remove the relationship like this
                    // $tag->setTask(null);

                    $entityManager->persist($ability);

                    // if you wanted to delete the Tag entirely, you can also do that
                    // $entityManager->remove($tag);
                }
            }

            $entityManager->persist($abilityHolder);
            $entityManager->flush();
            return $this->redirectToRoute('ability_holder_edit');
        }
        var_dump($abilityHolder);

        return $this->render('ability/edit.holder.html.twig', [
            'form' => $form->createView(),
        ]);
    }

    /**
     * @Route("/new", name="ability_new", methods="GET|POST")
     */
    /*public function new(Request $request)
    {
        $abilitys = new AbilityHolder();
        $ability1 = new Ability();
        $ability1->setIdItem('1');
        $ability1->setCode('code');
        $ability1->setReloadTime('1');
        $ability1->setDurationTime('1');
        $ability1->setIdAbilityType('1');

        // dummy code - this is here just so that the Ability has some tags
        // otherwise, this isn't an interesting example
        $abilitys->getAbilitys()->add($ability1);
        // end dummy code

        $form = $this->createForm(AbilityHolderType::class, $abilitys);

        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            // ... maybe do some form processing, like saving the Ability and Tag objects
        }

        return $this->render('ability/new-holder.html.twig', array(
            'form' => $form->createView(),
        ));
    }

    /**
     * @Route("/edit", name="ability_edit", methods="GET|POST")
     */
    /*public function edit(Request $request)
{
    $entityManager = $this->getDoctrine()->getManager();

    $originalAbilitys = new ArrayCollection();
    $abilityHolder = new AbilityHolder();

    // Create an ArrayCollection of the current Tag objects in the database
    foreach ($abilityHolder->getAbilitys() as $ability) {
        $originalAbilitys->add($ability);
    }

    $editForm = $this->createForm(AbilityHolderType::class, $abilityHolder);

    $editForm->handleRequest($request);

    if ($editForm->isSubmitted() && $editForm->isValid()) {
        // remove the relationship between the ability and the Task
        foreach ($originalAbilitys as $ability) {
            if (false === $abilityHolder->getAbilitys()->contains($ability)) {
                // remove the Task from the Tag
                $ability->getAbilitys()->removeElement($abilityHolder);

                // if it was a many-to-one relationship, remove the relationship like this
                // $ability->setTask(null);

                $entityManager->persist($ability);

                // if you wanted to delete the Tag entirely, you can also do that
                // $entityManager->remove($ability);
            }
        }

        $entityManager->persist($abilityHolder);
        $entityManager->flush();
    }

        return $this->render('ability/new-holder.html.twig', array(
            'form' => $editForm->createView(),
        ));

    // render some form template
}*/
}

树枝模板

{% extends 'base.html.twig' %}

{% block body %}
    {{ form_start(form) }}

    {% for ability in form.abilitys %}
        <li>{{ form_row(ability.idItem) }}</li>
        <li>{{ form_row(ability.code) }}</li>
        <li>{{ form_row(ability.reloadTime) }}</li>
        <li>{{ form_row(ability.durationTime) }}</li>
        <li>{{ form_row(ability.idAbilityType) }}</li>
    {% endfor %}

    {{ form_end(form) }}
{% endblock %}

error

在将/ {id}添加到路由后

after adding / {id} to routing

[Semantical Error] The annotation "@Entity" in class App\Entity\AbilityHolder was never imported. Did you maybe forget to add a "use" statement for this annotation? [Semantical Error] The annotation "@Entity" in class App\Entity\AbilityHolder was never imported. Did you maybe forget to add a "use" statement for this annotation?

1 个答案:

答案 0 :(得分:0)

我相信,这与表格无关。实际上,即使我没记错,即使您评论了整个动作,它仍然会失败。

这样做的原因是您设置控制器操作的方式:

/**
 * @Route("/ability-holder")
 * @ParamConverter (name ="abilityHolder", Class ="App\Entity\AbilityHolder") 
 */
class AbilityHolderController extends Controller
{

    /**
     * @Route("/edit", name="ability_holder_edit", methods="GET|POST")
     */
    public function edit(Request $request, AbilityHolder $abilityHolder)
    {   

默认情况下,Symfony将尝试使用类名类型提示来注入服务,但是,由于您指定$abilityHolder对应于param转换器,因此它确实会尝试在您的URL中查找标识符(默认情况下,{ {1}})。我没有看到上面的id,因此您需要指定它。

例如:

id

以上工作有效吗?

更新:

因此,正如我在下面的评论部分中所述,@Route("/edit/{id}", name="ability_holder_edit", methods="GET|POST") 不使用构造函数来创建对象的新实例。这会使您的对象(就非托管成员而言)处于半初始化状态。

一种解决方法是定义一个Doctrine侦听器:

postLoad