Зависимости в формах Symfony2

Я работаю над веб-приложением в Symfony2. Я пришел к моменту, когда мне нужен совет /объяснение от более опытного в Symfony.

У меня есть часть базы данных, которая настроена следующим образом:

У меня есть карты, которые принадлежат к набору атрибутов карт и состоят из значений карт.

У меня есть наборы атрибутов карты, которые имеют много атрибутов, атрибут карты может принадлежать многим наборам атрибутов карты (очевидно, отношение многих ко многим).

Затем, в зависимости от атрибута карты, атрибут имеет значение атрибута, например, текст имеет значение-текст типа varchar, а логическое значение - значение-логическое значение типа логический.

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

Итак, вот мой вопрос; Есть ли способ динамически генерировать поля ввода в форме в зависимости от сущности, выбранной пользователем. Я читал о событиях, но я не уверен, что они удовлетворяют мои потребности.

Это код для моих сущностей (я удалил его для получения и установки для более простого просмотра):

карта:

/**
 * card
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="clientsBundle\Entity\cardRepository")
 * @UniqueEntity(
 *      fields={"cardLabel"},
 *      message="A card with this label already exists"
 * )
 */
class card
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="card_label", type="string", length=999)
     */
    private $cardLabel;

    /**
     * @ORM\ManyToOne(targetEntity="project", inversedBy="project_cards")
     * @ORM\JoinColumn(name="project_id", referencedColumnName="id", onDelete = "SET NULL")
     */
    protected $card_project;

     /**
     * @ORM\ManyToOne(targetEntity="cardAttributeSet", inversedBy="cas_cards")
     * @ORM\JoinColumn(name="cas_id", referencedColumnName="id")
     **/
    protected $cardAttrSet;

    /**
     * @ORM\OneToMany(targetEntity="cardAttrValue", mappedBy="card", cascade={"persist"}, orphanRemoval=true)
     **/
    protected $card_values;

    /**
    * @ORM\ManyToMany(targetEntity="user", mappedBy="cards")
    */
    private $users;

    public function __construct() {
        $this->card_values = new ArrayCollection();
        $this->users = new ArrayCollection();
    }
}

Атрибут карты:

 /**
 * cardAttribute
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttributeRepository")
 * @UniqueEntity(
 *      fields={"name"},
 *      message="An attribute with this name already exists"
 * )
 */
class cardAttribute
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=255)
     */
    private $name;

    /**
     * @var string
     *
     * @ORM\Column(name="type", type="string", length=255)
     */
    private $type;
}

Набор атрибутов карты

 /**
 * cardAttributeSet
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttributeSetRepository")
 * @UniqueEntity(
 *      fields={"casLabel"},
 *      message="An attribute set with this label already exists"
 * )
 */
class cardAttributeSet
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    public $id;

    /**
     * @var string
     *
     * @ORM\Column(name="cas_label", type="string", length=255)
     */
    private $casLabel;

    /**
     * @ORM\OneToMany(targetEntity="card", mappedBy="cardAttrSet")
     */
    private $cas_cards;

    /**
     * @ORM\ManyToMany(targetEntity="cardAttribute")
     * @ORM\JoinTable(name="cas_attribute",
     *          joinColumns={@ORM\JoinColumn(name="cas_id", referencedColumnName="id")},
     *          inverseJoinColumns={@ORM\JoinColumn(name="attribute_id", referencedColumnName="id")}  
     *          )
     */
    private $attributes;

    public function __construct()
    {
        $this->cas_cards = new ArrayCollection();
        $this->attributes = new ArrayCollection();
    }
}

Значение атрибута карты

 /**
 * cardAttrValue
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="clientsBundle\Entity\cardAttrValueRepository")
 * @UniqueEntity(
 *      fields={"valueText"}
 * )
 */
class cardAttrValue
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="value_text", type="string", length=255, nullable=true)
     */
    private $valueText;

    /**
     * @var string
     *
     * @ORM\Column(name="value_varchar", type="string", length=255, nullable=true)
     */
    private $valueVarchar;

    /**
     * @var integer
     *
     * @ORM\Column(name="value_int", type="integer", nullable=true, nullable=true)
     */
    private $valueInt;

    /**
     * @var boolean
     *
     * @ORM\Column(name="value_boolean", type="boolean", nullable=true, nullable=true)
     */
    private $valueBoolean;

    /**
     * @ORM\ManyToOne(targetEntity="card", inversedBy="card_values")
     * @ORM\JoinColumn(name="card_id", referencedColumnName="id")
     **/
    private $card;

    /**
     * @ORM\ManyToOne(targetEntity="cardAttribute")
     * @ORM\JoinColumn(name="cardAttributes_id", referencedColumnName="id")
     **/
    private $cardAttribute;
}
7 голосов | спросил Dion Pieters 18 J0000006Europe/Moscow 2015, 12:25:31

1 ответ


0

Создайте тип формы CardAttributeValueType для CardAttributeValue entity, внутри этой формы добавьте поля в зависимости от переданного типа атрибута:

class CardAttributeValueType extends AbstractType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
        $value = $event->getData();
        $form = $event->getForm();

        if (!$value) {
            return;
        }

        switch ($value->getCardAttribute()->getType()) {
            case 'text':
                $form->add('valueVarchar', 'text');
                break;

            // Same for other attribute types
        }
     }
}

Затем добавьте тип поля collection для card_values внутри CardType и введите CardAttributeValueType как тип элемента коллекции.

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

UPDATE

public function getCardValues()
{
    $collection = new ArrayCollection();

    if (!$this->cardAttrSet) {
        return $collection;
    }

    // Add existing values
    foreach ($this->card_values as $value) {
        $collection[$value->getCardAttribute()->getId()] = $value;
    }

    // Get all attributes from the set and create values for missing attributes
    foreach ($this->cardAttrSet->getAttributes() as $attr) {
        if (!isset($collection[$attr->getId()])) {
            $value = new cardAttrValue();
            $value->setCardAttribute($attr);

            $collection[$attr->getId()] = $value;
        }
    }

    return $collection;
}
ответил Vadim Ashikhman 18 J0000006Europe/Moscow 2015, 15:17:13

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132