2013-03-07 2 views
9

В Symfony2, если я embed a collection of forms, указывая на отношения между несколькими отношениями в Доктрине и позволяю добавлять и удалять, если я удалю запись с начала, добавьте ее в конец , и отредактируйте некоторые в середине, как система знает, какие записи обновлять данные?Вложение коллекции форм Symfony2 с добавлением и удалением разрешено

В учебнике нет ничего, что передавало первичный ключ встроенных данных. При определенных обстоятельствах мои записи безошибочно удаляются и добавляются снова, а не редактируются (даже если нет изменений в конкретной записи). Это разбивает поля на записи, которые не включены в форму, и устанавливают их значения по умолчанию из модели БД.

Есть ли способ передать первичный ключ в форме и использовать ли он для выполнения обновлений, когда данные возвращаются?

+0

ли вы посмотрите разделы «Разрешить новые теги ...» и «Удаление тегов ...» в документе [this] (http://symfony.com/doc/current/cookbook/form/form_collections.html)? –

+0

@james_t Да. Я позволил им обоим. – rjmunro

+0

Попробуйте добавить идентификатор как скрытое поле в стиле встроенной формы! – hacfi

ответ

0

Один из способов передачи первичного идентификатора - использовать INDEX BY.

Например, у меня есть объект, называемый Клиент, и у Клиента есть несколько писем. В моем классе репозитория Customer я могу указать свою коллекцию для индексации по первому идентификатору электронной почты.

$qb->select('c, e') 
    ->leftJoin('c.emails', 'e', null, null, 'e.id') 
    ->where('c.id = :id'); 

Поступая таким образом, генерируемое имя входного тега будет

customer[emails][e.id][fieldName] 

После отправки формы, Symfony будет связывать значение запроса в соответствии с именами входных.

+0

Если входные имена «совпадают», что? Являются ли управляемые объекты хранятся в сеансе или что-то в этом роде? Если да, то что произойдет, если я открою два разных окна? Если нет, что, если строка была удалена или добавлена ​​в базу данных кем-то еще между мной, показывая форму и получая ее снова? Способ сопоставления строки в реляционной базе данных - это первичный ключ. Это цель первичного ключа. Первичный ключ не включается нигде в форму (что делает их частью входных имен хорошим местом). – rjmunro

+0

Ты абсолютно прав. Я отредактировал свой ответ, чтобы включить первичный ключ. –

+0

Вы - звезда сук! знаете ли вы, сколько дней я потратил на то, чтобы изменить свой вывод клиента [emails] [incremental_key] [fieldName] клиенту [emails] [database_record_id] [fieldName] - 3 дня, пытаясь всевозможно изменить вывод формы строитель - все время я искал не то место - спасибо !!! – coder4show

2

Если вы хотите проиндексировать коллекцию (по идентификатору сущности) для всех запросов, вы можете просто использовать аннотацию в своем классе сущности.

/** 
* @ORM\OneToMany(targetEntity="EntityClass", mappedBy="EntityVariable", indexBy="id") 
*/ 
private $collection; 
+0

Но тогда как эта информация используется в контроллере при обновлении? – Brian

+2

Рамка формы обрабатывает это автоматически. Вместо индексации элементов коллекции числами 1,2,3 ... коллекция затем индексируется идентификатором объектов. Поскольку индекс является как для объектов, получаемых из db, так и для тех, которые отправляются обратно через POST, структура знает, какая форма данных принадлежит какой-либо организации. – Akkumulator

+0

OK имеет смысл. Вы знаете, как это может работать для объектов с [Composite Keys] (http://docs.doctrine-project.org/en/2.0.x/tutorials/composite-primary-keys.html)? Поскольку на самом деле есть два идентификатора, а не один? – Brian

1

Основываясь на Akkumulator's answer and comment и некоторых экспериментов, я сделал это:

Создание новых полей (с помощью Javascript в described in the documentation) с __name__ замененные не рядом, но строкой: new_, за которым следует навсегда увеличивающееся число, которое не имеет никакого отношения к списку (например, new_1, new_2, new_3 ...)

Мне не нужно вставлять первичные ключи в формы, и мне не нужен индексBy - это хорошо , потому что indexBy чувствовал, что это было слишком далеко remo ved из формы, заканчивая тем, что имеет анти-шаблон Action at a distance.

Почему это работает:

  • PHP массивы не как в других языках. Они всегда словари, поэтому вы можете добавлять к ним строковые ключи, даже если у них есть только цифровые клавиши.
  • Поскольку коллекция Symfony отображаются по имени поля, новые поля не будут соответствовать существующим данным и удаленные поля не будут совпадать с существующими данными (и, таким образом, удаляются из набора)
Смежные вопросы