Symfony2 + Twig: Использование поля типа сущности для хранения несохраненных сущностей - PullRequest
2 голосов
/ 12 декабря 2011

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

По сути, у меня есть сущностьназывается Album, с которым может быть связано Subalbums.Поскольку пользователь создает Album сущность, используя форму, я хочу, чтобы он мог быстро создавать Subalbum сущности, которые будут сохранены позже.Я также хочу отобразить поле в произвольном формате, поэтому я не хочу использовать тег select с атрибутом multiple, вместо этого я вручную отображаю его в Twig (у меня не было проблем сthis).

Соотношение на Subalbum определяется следующим образом:

/**
 * @ORM\ManyToOne(targetEntity="Vhoto\AlbumBundle\Entity\Album")
 * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
 */
protected $parent;

Вот что я пробовал до сих пор ...

  1. Используйте поле типа entity в построителе форм, а затем вручную выведите поле.Проблема, с которой я столкнулся при использовании поля entity, заключается в том, что если пользователь создает Subalbum inline, symfony2 не нравится, когда я отправляю форму, потому что у него нет идентификатора.

  2. Используйте скрытый тип поля и попробуйте отправить несколько записей под одним и тем же именем поля (album[subalbums][]).Symfony2 также не нравится, когда я отправляю форму

Я предполагаю, что мне понадобится метод prePersist в моей сущности Album, чтобы создать любую Subalbum сущности, которые пользователь создал встроенными?

Надеюсь, есть гораздо более изящное решение, которое я просто полностью игнорирую.

Дайте мне знать, если что-то неясно.

1 Ответ

3 голосов
/ 12 декабря 2011

Существует действительно лучший способ сделать это.

Создание сущности

Создайте два Entity POPO и назначьте отношение many-to-one одному из полей дочерней сущности (вы сделали это правильно). Вы также можете определить one-to-many отношение в родительском

/**
 * @var ArrayCollection
 *
 * @ORM\OneToMany(targetEntity="Child", mappedBy="parent", cascade={"persist", "remove" }, orphanRemoval=true)
 */
protected $children;

Я не уверен, если это необходимо, но вы должны явно установить отношения в ваших установщиках, просто чтобы быть уверенными. Например, в вашей собственности:

public function addChild(ChildInterface $child)
{
    if(!$this->hasChild($child))
    {
        $this->children->add($child);
        $child->setParent($this);
    }
}

Doctrine, вероятно, не использует эти методы для привязки почтовых данных, но наличие этого для себя может решить некоторые сохраняющиеся проблемы.

Создание типа формы

Создание типа формы для обеих сущностей

/**
 * This would be the form type for your sub-albums.
 */
class ChildType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        //$builder->add(...);
        //...
    }

    public function getDefaultOptions(array $options) {
        return array(
            'data_class' => 'Acme\Bundle\DemoBundle\Entity\Child'
        );
    }

    public function getName()
    {
        return 'ChildType';
    }
}

/**
 * This would be the form type for your albums.
 */
class ParentType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        // This part here describes the relationship between the two
        // form types.
        $builder->add('children', 'collection', array(
            'type' => new ChildType(),
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true
        ));
    }

    public function getName()
    {
        return 'ChildType';
    }
}

С опциями allow_add и allow_delete вы фактически сообщили Symfony, что пользователь может добавлять или удалять сущности из коллекции. Опция prototype позволяет вам иметь прототип так называемой подформы на вашей странице.

Контроллер

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

foreach($parent->getChildren() as $child)
{
    if($child->getParent() === NULL)
    {
        $child->setParent($parent);
    }
}

View

Подготовьте шаблон вашей формы. Прототип должен быть обработан путем вызова form_rest(form) где-нибудь в вашем шаблоне. Если это не так или вы хотите настроить прототип, вот пример того, как это сделать.

<script id="ParentType_children_prototype" type="text/html">
    <li class="custom_prototype_sample">
        <div class="content grid_11 alpha">
            {{ form_widget(form.children.get('prototype').field1) }}
            {{ form_widget(form.children.get('prototype').field2) }}
            {{ form_rest(form.children.get('prototype') ) }}
        </div>
    </li>
</script>

Вы должны будете сделать форму динамической, используя JavaScript. Если вы используете jQuery, вы можете получить доступ к прототипу, вызвав $('ParentType_children_prototype').html(). При добавлении нового дочернего элемента в родительский элемент важно заменить все вхождения $$name$$ в прототипе на соответствующий порядковый номер.

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ Я только что заметил, что в справочнике по типу формы Symfony2 есть статья о CollectionType. У него есть хорошая альтернатива для реализации внешнего интерфейса для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...