【问题标题】:Unable to reverse value for property path [...]: The choice [...] does not exist or is not unique无法反转属性路径 [...] 的值:选项 [...] 不存在或不唯一
【发布时间】:2021-06-21 01:00:57
【问题描述】:

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

可能是由于规范更改颠倒了选择类型键和值。

我尝试将 choice_label 放在下面的参考中,但没有成功。

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

还有其他方法吗?

Symfony ChoiceType $choices - labels and values swapped

错误

This value is not valid.

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

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

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

类型

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

员工.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;
    }

文章.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;
    }

尝试过的代码 类型

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

错误

Notice: Undefined index: login_staff

【问题讨论】:

    标签: php symfony


    【解决方案1】:
        protected $password;
        protected $dbName;
        public function __construct ( $UserName, $Password, $DbName ) {
          $this->userName = $UserName;
          $this->password = $Password;...   
        {
                    public function __construct($staffService, $loginStaff)
                {
                    $this->staffService = $staffService;
                    
                    $this->loginStaff = $loginStaff;
                }
                    public function setCurrentStaff($currentStaff)
                {
                    $this->currentStaff = $currentStaff
                }
            
                    public function loadChoiceList($value = True)
                {
                    // Get the same shop staff as the login staff
                    $staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop($staff);
            
                    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);
                    }    Set choices_as_values to true. If you upgrade you have to change that.
    

    【讨论】:

      【解决方案2】:
          $staffs = $this->staffService->getStaffByShop($this->loginStaff->getShop());
      

      在我看来,这在编码方面有所不同,特别是第二个查询。

      【讨论】:

        【解决方案3】:

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

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

        使用 ChoiceType,如下例所示:

        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 = [
            1 => new Staff(1),
            2 => new Staff(2),
            3 => new Staff(3),  
        ];
        

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

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

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

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

        【讨论】:

        • 感谢您的回答。我试过了,但我绊倒了依赖注入。如何注入$options?我已经添加了我尝试过的代码,您可以查看一下吗?
        • DI 仅适用于服务。要传递自定义选项,请在表单类型的 buildForm 方法中使用 options 参数。检查我编辑的答案。
        • 我试过了,但是我得到了以下错误:The value of type "object" cannot be converted to a valid array key. 看来$staff 是一个对象。当我做var_dump时,它变成了如下。 array(17) { [0]=> object(AppBundle\Model\Entity\Staff)#650 (24) { ["id":protected]=> int(305)...看来这是因为数组的每一项都是StaffEntity的对象。
        猜你喜欢
        • 2019-02-09
        • 1970-01-01
        • 2016-06-06
        • 1970-01-01
        • 2019-03-28
        • 2019-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多