无法反转属性路径 [...] 的值:选项 [...] 不存在或不唯一 [英] Unable to reverse value for property path [...]: The choice [...] does not exist or is not unique

查看:25
本文介绍了无法反转属性路径 [...] 的值:选项 [...] 不存在或不唯一的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Symfony 2.8更新到3.0并验证运行后,发现由于验证错误,作者无法保存.

可能是由于规范更改使 Choice Type 键和值颠倒了.

我尝试将 choice_label 放在下面的参考中,但没有用.

我也试过array_flip $staffs,但显示改变了,我无法保存.

还有什么办法吗?

Symfony ChoiceType $choices - 标签和值交换

错误

此值无效.无法反转属性路径author"的值:选择9"不存在或不唯一.

前员工选择列表

使用Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;使用 Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList;类 StaffChoiceList 扩展了 LazyChoiceList{公共函数 __construct($staffService, $loginStaff){$this->staffService = $staffService;$this->loginStaff = $loginStaff;}公共函数 setCurrentStaff($currentStaff){$this->currentStaff = $currentStaff;}公共函数 loadChoiceList($value = null){//获取与登录员工相同的店铺员工$staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());如果当前员工不包括在获取的员工中(由于调动等),则添加到最后如果 ($this->currentStaff && !array_search($this->currentStaff, $staffs)) {$staffs[] = $this->currentStaff;}return new ChoiceList($staffs, $staffs);}}

在 StaffChoiceloader 之后

使用Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;使用 Symfony\Component\Form\Choicelist\ArrayChoiceList;类 StaffChoiceLoader 实现 ChoiceLoaderInterface{公共函数 loadChoiceList($value = null){$staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());如果 ($this->currentStaff && !array_search($this->currentStaff, $staffs)) {$staffs[] = $this->currentStaff;}return new arrayChoiceList($staffs, null);}公共函数 loadChoicesForValues(array $values, $value = null){//没有预设数据时优化如果(空($选择)){返回数组();}$values = array();foreach ($choices 作为 $choice){$values[] = (string) $this->loginStaff->getId();}返回 $values;}公共函数 loadValuesForChoices(array $choices, $value = null){//无发送时优化如果(空($值)){返回数组();}//从ID中获取实体并返回需要的数据返回 $this->staffService->getStaffByShop($this->loginStaff->getShop());}}

类型

 $authorChoiceList = new StaffChoiceLoader($this->staffService, $options['login_staff']);$builder->add(作者", EntityType::class, array(必需"=>真的,类"=>AppBundle:员工",选择加载器"=>$作者选择列表,选择标签"=> 函数 ($value) {返回 $value;},));$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($authorChoiceList) {$article = $event->getData();$authorChoiceList->setCurrentStaff($article->getAuthor());});公共函数 configureOptions(OptionsResolver $resolver){$resolver->setDefaults(array(validation_groups"=>函数 (FormInterface $form) {$article = $form->getData();返回 $this->getValidationGroups($article->getArticleStatus());},));}

员工.php

/*** __toString** @return 字符串*/公共函数 __toString(){返回 $this->staffName;}/*** 设置员工姓名** @param string $staffName* @return 员工*/公共函数 setStaffName($staffName){$this->staffName = $staffName;返回 $this;}/*** 获取员工姓名** @return 字符串*/公共函数 getStaffName(){返回 $this->staffName;}

文章.php

/*** @ORM\ManyToOne(targetEntity=员工")* @ORM\JoinColumn(name=author_id", referencedColumnName=id", nullable=true)*/受保护的 $author;/*** 设置作者** @param \AppBundle\Model\Entity\Staff $author* @return 文章*/公共函数 setAuthor(\AppBundle\Model\Entity\Staff $author = null){$this->author = $author;返回 $this;}/*** 获取作者** @return \AppBundle\Model\Entity\Staff*/公共函数 getAuthor(){返回 $this->author;}

尝试代码输入

 public function __construct($staffService, array $options = []){$this->staffService = $staffService;$this->loginStaff = $options['login_staff'];$this->currentStaff = $options['login_staff'];}

错误

注意:未定义索引:login_staff

解决方案

先尝试让它变得简单.如果您的 ChoiceLoader 不起作用,请尽量避免它.在获得最少的工作示例后,您可以对其进行重构.

EntityType 仅在您使用 QueryBuilder 从数据库中获取选择时才有用.

使用 ChoiceType 如下例所示:

使用Symfony\Component\Form\Extension\Core\Type\ChoiceType;使用 App\Entity\Staff;类 StaffType 扩展了 AbstractType{公共函数 __construct($staffService){$this->staffService = $staffService;}公共函数 buildForm(FormBuilderInterface $builder, array $options): void{$currentStaff = $options['currentStaff'];$loginStaff = $options['loginStaff'];$staff = $this->staffService->getStaffByShop($loginStaff->getShop());//如果当前人员没有包含在获取到的人员中(因为转职等),添加到最后如果 ($currentStaff && !array_search($currentStaff, $staffs)) {$staff[] = $currentStaff;}$builder->add('author', ChoiceType::class, ['选择' =>$员工,'选择标签' =>功能(员工 $employee, $key){返回 $employee->getName();}]);}}

员工数组必须包含唯一键,例如:

$staff = [1 =>新员工(1),2 =>新员工(2),3 =>新员工(3),];

使用自定义选项在控制器中构建表单:

$options = ['currentStaff' =>$currentStaff,'登录员工' =>$登录员工,];$this->createForm(StaffType::class, $data, $options);

要访问$this->staffService,请在表单类型中使用依赖注入.对于 $this->currentStaff$this->loginStaff 使用 $options.

它对你有用吗?如果没有,请提供 $staff 数组的结构.

After updating from Symfony 2.8 to 3.0 and verifying the operation, it was found that the author could not save due to a validation error.

Probably due to a specification change that reverses the Choice Type key and value.

I tried putting choice_label in the reference below, but it didn't work.

I also tried array_flip $staffs, but the display changed and I couldn't save it.

Is there any other way?

Symfony ChoiceType $choices - labels and values swapped

Error

This value is not valid.

Unable to reverse value for property path "author":
 The choice "9" does not exist or is not unique.

Before StaffChoicelist

use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList;
use Symfony\Component\Form\Extension\Core\ChoiceList\LazyChoiceList;

class StaffChoiceList extends LazyChoiceList
{
    public function __construct($staffService, $loginStaff)
    {
        $this->staffService = $staffService;
        $this->loginStaff = $loginStaff;
    }

    public function setCurrentStaff($currentStaff)
    {
        $this->currentStaff = $currentStaff;
    }

    public function loadChoiceList($value = null)
    {
        // Get the same shop staff as the login staff
        $staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());

        If the current staff is not included in the acquired staff (due to transfer etc.), add it to the end
        if ($this->currentStaff && !array_search($this->currentStaff, $staffs)) {
            $staffs[] = $this->currentStaff;
        }
            return new ChoiceList($staffs, $staffs);
    }
}

After StaffChoiceloader

use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
use Symfony\Component\Form\Choicelist\ArrayChoiceList;

class StaffChoiceLoader implements ChoiceLoaderInterface
{
    public function loadChoiceList($value = null)
    {
        $staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());

        if ($this->currentStaff && !array_search($this->currentStaff, $staffs)) {
            $staffs[] = $this->currentStaff;
        }
            return new arrayChoiceList($staffs, null);
    }
    public function loadChoicesForValues(array $values, $value = null)
    {
        // Optimized when no data is preset
        if (empty($choices))
        {
            return array();
        }

        $values = array();
        foreach ($choices as $choice)
        {
            $values[] = (string) $this->loginStaff->getId();
        }

        return $values;
    }

    public function loadValuesForChoices(array $choices, $value = null)
    {
        // Optimized when nothing is sent
        if (empty($values))
        {
            return array();
        }

        // Get the entity from the ID and return the required data
        return $this->staffService->getStaffByShop($this->loginStaff->getShop());
    }
}

Type

        $authorChoiceList = new StaffChoiceLoader($this->staffService, $options['login_staff']);
        $builder->add("author", EntityType::class, array(
            "required" => true,
            "class" => "AppBundle:Staff",
            "choice_loader" => $authorChoiceList,
            "choice_label" =>function ($value) {
              return $value;
            },
        ));
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($authorChoiceList) {
            $article = $event->getData();
            $authorChoiceList->setCurrentStaff($article->getAuthor());
        });
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            "validation_groups" => function (FormInterface $form) {
                $article = $form->getData();
                return $this->getValidationGroups($article->getArticleStatus());
            },
        ));
    }

Staff.php

    /**
     * __toString
     *
     * @return string
     */
    public function __toString()
    {
        return $this->staffName;
    }
    /**
     * Set staffName
     *
     * @param string $staffName
     * @return Staff
     */
    public function setStaffName($staffName)
    {
        $this->staffName = $staffName;

        return $this;
    }

    /**
     * Get staffName
     *
     * @return string
     */
    public function getStaffName()
    {
        return $this->staffName;
    }

Article.php

    /**
     * @ORM\ManyToOne(targetEntity="Staff")
     * @ORM\JoinColumn(name="author_id", referencedColumnName="id", nullable=true)
     */
    protected $author;
    /**
     * Set author
     *
     * @param \AppBundle\Model\Entity\Staff $author
     * @return Article
     */
    public function setAuthor(\AppBundle\Model\Entity\Staff $author = null)
    {
        $this->author = $author;

        return $this;
    }

    /**
     * Get author
     *
     * @return \AppBundle\Model\Entity\Staff
     */
    public function getAuthor()
    {
        return $this->author;
    }

Tried Code Type

    public function __construct($staffService, array $options = [])
    {
        $this->staffService = $staffService;
        $this->loginStaff = $options['login_staff'];
        $this->currentStaff = $options['login_staff'];
    }

Error

Notice: Undefined index: login_staff

解决方案

Try make it simple first. If your ChoiceLoader doesn't work, try to avoid it. After you get minimal working example you can refactor it.

EntityType is usefull only if you use QueryBuilder for obtaining choices from database.

Use ChoiceType as in example below:

use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use App\Entity\Staff;

class StaffType extends AbstractType
{
    public function __construct($staffService)
    {
        $this->staffService = $staffService;
    }

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $currentStaff = $options['currentStaff'];
        $loginStaff = $options['loginStaff'];
    
        $staff = $this->staffService->getStaffByShop($loginStaff->getShop());
        // If the current staff is not included in the acquired staff (due to transfer etc.), add it to the end
        if ($currentStaff && !array_search($currentStaff, $staffs)) {
            $staff[] = $currentStaff;
        }
    
        $builder->add('author', ChoiceType::class, [
            'choices' => $staffs,
            'choice_label' => function(Staff $employee, $key) {
                return $employee->getName();
            }
        ]);
    }
}

Staff array must contains unique keys e.g.:

$staff = [
    1 => new Staff(1),
    2 => new Staff(2),
    3 => new Staff(3),  
];

Build your form in controller with custom options:

$options = [
    'currentStaff' => $currentStaff,
    'loginStaff' => $loginStaff,
];
$this->createForm(StaffType::class, $data, $options);

For accessing $this->staffService use dependency injection in your form type. And for $this->currentStaff and $this->loginStaff use $options.

Does it works for you? If not, please provide structure of $staff array.

这篇关于无法反转属性路径 [...] 的值:选项 [...] 不存在或不唯一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆