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

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

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

1

Решение

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

  • Вы можете перехватить событие submit в JavaScript и использовать эти флажки для построения данных, которые должны быть отправлены обратно в Symfony, в данных для исходного поля (и снять флажки, чтобы они не отправлялись на сервер)
  • Вы можете проверить наличие этих полей при отправке формы в вашем контроллере и использовать их для создания необходимых данных (также сбросьте их, чтобы symfony не жаловался при проверке формы)
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]