Symfony: как сделать, чтобы отредактировать атрибут класса json_array со списком флажков?

1

В моем приложении 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 %}

Однако данные, возвращаемые при отправке моей формы, - это исходный вывод данных, а не измененные данные. Наверное, я сделал это неправильно в представлении. Как я могу правильно редактировать эти данные и иметь возможность манипулировать им функцией обратного преобразования моего трансформатора данных?

Теги:
forms
checkbox

1 ответ

1
Лучший ответ

Ваша проблема заключается в том, что вы создаете несколько полей ввода (флажки), о которых Symfony ничего не знает. Фактически, когда вы отправляете форму, она, вероятно, собирается исключить исключение, заявив, что она получила некоторые поля, которых она не ожидала. Вам нужно преобразовать эти поля в нечто, что может понять symfony. Вы можете сделать это двумя способами:

  • Вы можете перехватить событие отправки в JavaScript и использовать эти флажки для создания данных, которые должны быть отправлены обратно в symfony в данные для исходного поля (и снять флажки, чтобы они не были отправлены на бэкэнд)
  • Вы можете проверить наличие этих полей, когда форма отправлена в ваш контроллер и использовать их для создания необходимых вам данных (также отключите их, чтобы symfony не жаловался при проверке формы)
  • 0
    хорошо, спасибо, я понимаю это. Как данные должны быть отправлены обратно? Распознает ли отправленные данные по id поля? Как ни странно, при отправке формы нет исключений, я просто получаю тот же массив данных, который получаю в виде, если я дам дамп {{dump (form.vars.data)}}
  • 0
    Итак, наконец, я переписал форму и создал checboxes в цикле в моем типе формы. Затем я убил все это и создал функцию ajax, которая обновляла бы каждый параметр json, гораздо проще, чище и быстрее. Спасибо

Ещё вопросы

Сообщество Overcoder
Наверх
Меню