【问题标题】:symfony : how to render edit a class json_array attribute with a list of checkboxes?symfony:如何使用复选框列表呈现编辑类 json_array 属性?
【发布时间】:2016-01-24 23:11:30
【问题描述】:

在我的 symfony2 应用程序中,我有一个 json_array 类型的属性:

/**
 * @ORM\Column(name="rights", type="json_array", nullable=true)
 */
protected $rights = array();

此属性的数据是一个关联数组,如下所示:

    $allRights = array(
        Associate::READ_PROFILE => array('all' => false),
        Associate::UPDATE_PROFILE => array('all' => false),
        Associate::READ_CONTACT => array('all', 'created' => false),
);

我希望能够使用复选框集合来编辑此属性,即。我想要第一级的每个键一行,然后第二级的每个键一个复选框。

我有一个表单类型,它调用自定义类型:

<?php

namespace AppBundle\Form\User;

use AppBundle\Entity\User\Associate;
use AppBundle\Form\DataTransformer\RightsToArrayTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Validator\Constraints as Assert;

class AssociateRightsType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('rights', 'fmu_rights', array(
                'label' => false,
            ));
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User\Associate',
            'validation_groups' => array('Default', 'rights'),
            'cascade_validation' => true,
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_user_associate_rights';
    }
}

在这个自定义类型中,我添加了一个 dataTransformer :

<?php

namespace AppBundle\Form\Type;

use AppBundle\Application\User\AssociateManager;
use AppBundle\Entity\User\Associate;
use AppBundle\Form\DataTransformer\RightsToArrayTransformer;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class RightsType extends AbstractType
{
    /**
     * @var AssociateManager
     */
    private $associateManager;

    public function __construct(AssociateManager $associateManager)
    {
        $this->associateManager = $associateManager;
    }

    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new RightsToArrayTransformer();
        $builder->addModelTransformer($transformer);


    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'fmu_rights';
    }

}

在这个数据转换器中,我确保数据以正确的格式输出:

<?php

namespace AppBundle\Form\DataTransformer;

use AppBundle\Entity\User\Associate;
use Symfony\Component\Form\DataTransformerInterface;

class RightsToArrayTransformer implements DataTransformerInterface
{
    /**
     * @param mixed $data
     * @return array|mixed
     */
    public function transform($data)
    {
        return is_array($data) ? $data + $this->getRights() : $this->getRights();
    }

    /**
     * @param mixed $data
     * @return array
     */
    public function reverseTransform($data)
    {
        return $data;
    }

    private function getRights()
    {
        $allRights = array(
            Associate::READ_PROFILE => array('all'),
            Associate::UPDATE_PROFILE => array('all'),
            Associate::READ_CONTACT => array('all', 'created'),
            Associate::UPDATE_CONTACT => array('all', 'created'),
            Associate::DELETE_CONTACT => array('all', 'created'),
            Associate::IS_BOSS => array('all'),
        );

        foreach ($allRights as $right => $parameters) {
            $allRights[$right] = array();
            foreach ($parameters as $parameter) {
                $allRights[$right][$parameter] = false;
            }

        }

        return $allRights;
    }
}

我有一个自定义视图,可以产生正确的视觉输出:

{% block fmu_rights_widget %}

    {% if attr.class is defined %}
        {% set attr = attr|merge({'class': attr.class ~ ' input-sm form-control fmu_rights'}) %}
    {% endif %}

    {% set rights = form.vars.data %}

    {% for right, parameters in rights %}
        <div class="row padding-v">
            <div class="col-md-2">
                {{ right }}
            </div>
            <div class="col-md-10">
                {% for parameter, value in parameters %}
                    {% set name = id ~ '[' ~ loop.index ~ ']' ~ right ~ '[' ~ parameter ~ ']' %}
                        <label for="{{ name }}">{{ parameter }}</label>
                        <input type="checkbox" id="{{ name }}" name="{{ name }}" {% if value %}checked{% endif %}>
                {% endfor %}
            </div>
        </div>
    {% endfor %}

{% endblock %}

但是,我发送表单时返回的数据是原始数据输出,而不是修改后的数据。 我想我在视图中做错了。我怎样才能正确编辑这些数据,并能够通过我的数据转换器的反向转换功能来操作它?

【问题讨论】:

    标签: php forms symfony checkbox transformer


    【解决方案1】:

    您的问题是您正在创建许多 symfony 不知道的输入字段(复选框)。事实上,当你提交表单时,它可能会抛出一个异常,说它收到了一些它没有预料到的字段。你需要将这些字段转换成 symfony 可以理解的东西。你可以通过两种方式做到这一点:

    • 您可以在 JavaScript 中拦截提交事件,并使用这些复选框在原始字段的数据中构造应发送回 symfony 的数据(并取消设置复选框,以便它们不会发送到后端)李>
    • 您可以在您的控制器中提交表单时测试这些字段是否存在,并使用它们来构造您需要的数据(也可以取消设置,以便 symfony 在验证表单时不会报错)

    【讨论】:

    • 好的,谢谢,我明白了。数据应该如何发回?它是否从字段的 id 识别发送的数据?奇怪的是,发送表单时也不例外,如果我转储 {{ dump(form.vars.data) }},我只会得到与视图中相同的数据数组
    • 好的,所以最后,我重写了表单并在我的表单类型的循环中创建了复选框。然后我把它全部杀掉并创建了一个 ajax 函数,它可以更新每个 json 参数,更容易、更干净、更快速。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    相关资源
    最近更新 更多