2015-06-18 17 views
7

Tôi đang làm việc trên một ứng dụng web trong Symfony2. Tôi đã đến một điểm mà trong đó tôi cần một số lời khuyên/giải thích từ một số cao cấp hơn trong Symfony.Phụ thuộc vào các biểu mẫu Symfony2

Tôi có một phần của cơ sở dữ liệu của tôi được thiết lập như sau:

Tôi có thẻ mà thuộc về một thuộc tính thẻ thiết lập và bao gồm các giá trị thẻ.

Tôi có các thuộc tính thẻ có nhiều thuộc tính, thuộc tính thẻ có thể thuộc về nhiều tập hợp thuộc tính thẻ (rõ ràng là mối quan hệ nhiều đến nhiều).

Sau đó, tùy thuộc vào thuộc tính thẻ thuộc tính có giá trị thuộc tính, ví dụ: văn bản có giá trị là loại varchar và boolean có giá trị_boolean kiểu boolean.

Bạn có thể tưởng tượng khi tạo biểu mẫu để tạo thẻ mới, biểu mẫu cần tạo trường nhập tùy thuộc vào thuộc tính thẻ thuộc thuộc tính và tùy thuộc vào thuộc tính thuộc về tập thuộc tính?

Vì vậy, đây là câu hỏi của tôi; có cách nào để tự động tạo các trường nhập trong biểu mẫu tùy thuộc vào thực thể do người dùng chọn hay không. Tôi đã đọc về các sự kiện nhưng tôi không chắc chắn rằng họ đáp ứng nhu cầu của tôi.

Đây là mã cho các đơn vị của tôi (tôi loại bỏ để Getters and Setters cho một cái nhìn đơn giản hơn):

thẻ:

/** 
* 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(); 
    } 
} 

Thẻ Thuộc tính:

/** 
* 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; 
} 

Thuộc tính thẻ bộ

/** 
* 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(); 
    } 
} 

thẻ Attribute Value

/** 
* 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; 
} 

Trả lời

3

Tạo một loại hình thức CardAttributeValueType cho CardAttributeValue tổ chức nào, bên trong mẫu đơn này thêm các trường tùy thuộc vào loại thuộc tính thông qua:

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 
     } 
    } 
} 

Sau đó, thêm collection loại trường cho card_values bên trong CardType loại và thông tin biểu mẫu CardAttributeValueType làm loại mục bộ sưu tập.

Trong phương thức Card chỉnh sửa đối tượng getCardValues() để nó sẽ trả về mọi thuộc tính từ CardAttributeSet, không chỉ các thuộc tính có giá trị tồn tại.

CẬP NHẬT

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; 
} 
+0

Nó làm việc, cảm ơn rất nhiều! –

+0

Vadim Ashikhman, chỉ có bản chỉnh sửa tác phẩm của tôi, vì thẻ có giá trị trong đó. Tho Tôi vẫn cần phải đảm bảo getCardValues ​​() của tôi trả về mọi thuộc tính từ CardAttributeSet, không chỉ các thuộc tính mà các thực thể giá trị tồn tại.Tôi đã thực hiện một số nghiên cứu nhưng tôi khá bối rối ngay bây giờ, hehe. Bạn có thể giúp tôi thêm một lần nữa không? –

+1

Tôi đã cập nhật câu trả lời của mình. Tôi havent thử nghiệm phương pháp này, tôi nghĩ rằng bạn sẽ có được ý tưởng. –

Các vấn đề liên quan