2014-11-23 5 views
14

Я представляю форму с полем сущности в symfony.symfony: не можем ли мы иметь скрытое поле объекта?

Он хорошо работает, когда я выбираю обычное поле объекта.

$builder 
    ->add('parent','entity',array(
      'class' => 'AppBundle:FoodAnalytics\Recipe', 
      'attr' => array(
       'class' => 'hidden' 
      ) 
     )) 

Он выдает следующее сообщение об ошибке, когда я выбираю -> добавить («родитель», «скрытый»):

просматривать данные виде, как ожидается, будет типа скаляр, массив или экземпляр \ ArrayAccess, но является экземпляром класса AppBundle \ Entity \ FoodAnalytics \ Recipe. Вы можете избежать этой ошибки на , установив опцию «data_class» на «AppBundle \ Entity \ FoodAnalytics \ Recipe» или добавив вид трансформатора , который преобразует экземпляр класса AppBundle \ Entity \ FoodAnalytics \ Recipe к скаляру, массиву или экземпляр из \ ArrayAccess. 500 Внутренняя ошибка сервера - LogicException

Не можем ли мы иметь скрытые поля объекта? Почему нет? Должен ли я поместить другое скрытое поле для получения идентификатора объекта?

EDIT:

В принципе, то, что я пытаюсь сделать, это гидрат форму перед отображением его, но мешает пользователю изменить один из его полей (родительский здесь). Это потому, что мне нужно передать Id как параметр, и я не могу сделать это в URL-адресе формы.

ответ

15

Я думаю, вы просто смущены о типах полей и о том, что они представляют.

entity Поле является видом choice Поле. Поля выбора зависят от значений, выбираемых пользователем в форме. Когда эта форма отображается, Symfony будет генерировать список возможных вариантов, основанных на базовом классе поля сущности, а значение каждого выбора в списке - это идентификатор соответствующего объекта. После отправки формы Symfony увлажнит объект для вас, представляющий выбранный объект. Поле entity обычно используется для передачи ассоциаций сущностей (например, список roles, который вы можете выбрать для назначения user).

Если вы просто пытаетесь создать местозаполнитель для поля идентификатора объекта, то вы должны использовать вход hidden. Но это работает только в том случае, если класс формы, который вы создаете, представляет собой сущность (т.е. форма data_class формы относится к сущности, которую вы определили). Затем поле идентификатора правильно сопоставляет идентификатор объекта типа, определенного формой data_class.

EDIT: Одним из решений вашей конкретной ситуации, описанной ниже, было бы создание нового типа поля (назовем его EntityHidden), который расширяет тип поля hidden, но обрабатывает преобразование данных для преобразования в/из объекта/идентификатора. Таким образом, ваша форма будет содержать идентификатор объекта как скрытое поле, но приложение будет иметь доступ к самой сущности после отправки формы. Конечно, преобразование выполняется преобразователем данных.

Вот пример такой реализации, для потомков:

namespace My\Bundle\Form\Extension\Type; 

use Symfony\Component\Form\AbstractType; 
use Symfony\Component\Form\FormBuilderInterface; 
use Symfony\Component\Form\DataTransformerInterface; 

/** 
* Entity hidden custom type class definition 
*/ 
class EntityHiddenType extends AbstractType 
{ 
    /** 
    * @var DataTransformerInterface $transformer 
    */ 
    private $transformer; 

    /** 
    * Constructor 
    * 
    * @param DataTransformerInterface $transformer 
    */ 
    public function __construct(DataTransformerInterface $transformer) 
    { 
     $this->transformer = $transformer; 
    } 

    /** 
    * @inheritDoc 
    */ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     // attach the specified model transformer for this entity list field 
     // this will convert data between object and string formats 
     $builder->addModelTransformer($this->transformer); 
    } 

    /** 
    * @inheritDoc 
    */ 
    public function getParent() 
    { 
     return 'hidden'; 
    } 

    /** 
    * @inheritDoc 
    */ 
    public function getName() 
    { 
     return 'entityhidden'; 
    } 
} 

Просто обратите внимание, что в классе формы типа, все, что вам нужно сделать, это присвоить скрытый объект своего соответствующего свойства поля формы (в пределах модель модели/класс данных), а Symfony будет генерировать скрытый ввод HTML правильно с идентификатором объекта как его значением. Надеюсь, это поможет.

+0

Ну, у меня есть реальный объект с ID, и этот объект имеет родительский элемент того же класса. это отношение родитель-ребенок сопоставляется с использованием расширения дерева доктрины. Я создаю процедуру, позволяющую создать новую сущность из существующей, и при этом я устанавливаю родительское поле в старый объект. Поэтому мое родительское поле отображается (onetomany отношения), но я не хочу, чтобы пользователь мог его модифицировать ...здесь я не могу изменить data_class всего типа, так как он уже установлен –

+0

, пока я просто скрыл элемент управления с помощью css ... –

+1

Посмотрите на преобразователи данных: http://symfony.com/doc/current/cookbook /form/data_transformers.html Они позволят вам преобразовать сущность в и из идентификатора. Просто имейте в виду, что использование скрытого поля не мешает пользователю изменять значение. Просто делает это немного сложнее. – Cerad

0

Это может быть достигнуто довольно чисто с помощью формы, используя стандартную тему поля hidden вместо того, что для объекта. Я думаю, что использование трансформаторов, вероятно, слишком велико, учитывая, что скрытые и выбранные поля будут иметь тот же формат.

{% block _recipe_parent_widget %} 
    {%- set type = 'hidden' -%} 
    {{ block('form_widget_simple') }} 
{% endblock %} 
+0

Но используя этот подход, вы должны сами получить объект отправленного 'id' (в своем контроллере), проверьте, существует ли сущность с этим' id' и возвращает правильное сообщение, если объект не найден. Это ИМХО, безусловно, неправильный подход! – baris1892

+0

Нет. Он работает так же, как тип объекта. Вы не меняете тип формы - просто тему виджета. Единственное различие заключается в том, что он будет отображать '' вместо '