2017-03-28 33 views
11

parent için kullanıcı girdisi tarafından verilen bir dizi çocuk eklemesi gereken bir işlem geliştirmeye çalışmakla meşguldüm.Çocuk nesnelerini, henüz var olmadıklarında bir üst nesneye ekleyin

Çocukların 3 özelliği vardır ve bunları birleştirir, her çocuk her zaman benzersiz olmalıdır.

Ben Symfony'de ve Doktrin ve benim temel ebeveyn sınıfının faydalanmak şuna benzer:

class Parent 
{ 
    /** 
    * @var Child[]|ArrayCollection 
    * 
    * @ORM\OneToMany(targetEntity="Child", mappedBy="parent") 
    * @ORM\OrderBy({"dateCreated": "DESC"}) 
    */ 
    private $childs; 

    /** 
    * Add child 
    * 
    * @param \AppBundle\Entity\Child $child 
    * 
    * @return Parent 
    */ 
    public function addChild(\AppBundle\Entity\Child $child) 
    { 
     $this->childs[] = $child; 
     $child->setParent($this); 
     return $this; 
    } 

    /** 
    * Remove child 
    * 
    * @param \AppBundle\Entity\Child $child 
    */ 
    public function removeChild(\AppBundle\Entity\Child $child) 
    { 
     $this->childs->removeElement($child); 
    } 

    /** 
    * Get childs 
    * 
    * @return \Doctrine\Common\Collections\Collection 
    */ 
    public function getChilds() 
    { 
     return $this->childs; 
    } 
} 

böyle Çocuğum sınıf bakmak (yine gerçekten temel): Sonra

class Child 
{ 
    /** 
    * @var int 
    * 
    * @ORM\Column(name="cupboard", type="integer") 
    */ 
    private $cupboard; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="shelf", type="integer") 
    */ 
    private $shelf; 

    /** 
    * @var int 
    * 
    * @ORM\Column(name="item", type="integer") 
    */ 
    private $item; 

    /** 
    * @var Parent 
    * 
    * @ORM\ManyToOne(targetEntity="Parent", inversedBy="childs") 
    * @ORM\JoinColumns({ 
    * @ORM\JoinColumn(name="parent_id", referencedColumnName="id") 
    * }) 
    */ 
    private $parent; 

    /** 
    * Set cupboard 
    * 
    * @param string $cupboard 
    * 
    * @return Child 
    */ 
    public function setCupboard($cupboard) 
    { 
     $this->cupboard = $cupboard; 

     return $this; 
    } 

    /** 
    * Get cupboard 
    * 
    * @return int 
    */ 
    public function getCupboard() 
    { 
     return $this->cupboard; 
    } 

    /** 
    * Set shelf 
    * 
    * @param string $shelf 
    * 
    * @return Child 
    */ 
    public function setShelf($shelf) 
    { 
     $this->shelf = $shelf; 

     return $this; 
    } 

    /** 
    * Get shelf 
    * 
    * @return int 
    */ 
    public function getShelf() 
    { 
     return $this->shelf; 
    } 

    /** 
    * Set item 
    * 
    * @param string $item 
    * 
    * @return Child 
    */ 
    public function setItem($item) 
    { 
     $this->item = $item; 

     return $this; 
    } 

    /** 
    * Get item 
    * 
    * @return int 
    */ 
    public function getItem() 
    { 
     return $this->item; 
    } 

    /** 
    * Set parent 
    * 
    * @param Parent $parent 
    * 
    * @return Child 
    */ 
    public function setParent(Parent $parent) 
    { 
     $this->parent = $parent; 

     return $this; 
    } 

    /** 
    * Get parent 
    * 
    * @return Parent 
    */ 
    public function getParent() 
    { 
     return $this->parent; 
    } 
} 

Bir var Bunun için çocuklar oluşturması gereken parent nesnesine (bir düzenleme eylemiyle aynı türde) eylem. Ben (belirli ebeveyn için) tıkladığında form üç giriş alanlara sahip olduğundan oluşturulur:

  • Dolap
  • öğelerin Raf
  • Numara

Ardından kullanıcı belirtmek zorundadır

  • tamsayılarla hangi dolaba ve hangi rafa kaç öğe eklemek istediğini. Verilen rafta söz konusu dolapta öğe (tamsayı) zaten mevcutsa, tekrar yapmamalı, ancak sonraki bir sonraki tam sayı tamsayısı öğe için kullanılmalıdır.

    Bunu olabildiğince basit hale nasıl getirebilirim? addChild işlevini Parent sınıfından kullanabileceğimi anlıyorum, ancak emin değilim.

    Şimdiye kadar denediğim şey, bir dizi oluşturmak ve dolap ve rafa göre tüm öğeleri gruplamak ve eğer o dizide öğe yoksa, oluşturulması gerekir.

    Bu

    benim kodudur:

    public function addItemAction(Request $request, $id = null){ 
        $parent = $this->admin->getSubject(); 
    
        if (!$parent) { 
         throw new NotFoundHttpException(sprintf('Unable to find the object with id: %s', $id)); 
        } 
    
        $em = $this->getDoctrine()->getManager(); 
    
        $form = $this->createForm(AddItemType::class); 
        $form->handleRequest($request); 
    
        if ($form->isSubmitted() && $form->isValid()) { 
         $kids = $popUnit->getChilds(); 
         $formParams = $request->request->get('add_item'); 
    
         $units = array(); 
         foreach ($kids as $kid) { 
          $units[$kid->getCupboard()][$kid->getShelf()][$kid->getItem()] = $kid->getItem(); 
         } 
    
         $givenShelf = $units[$formParams['cupboard']][$formParams['shelf']]; 
    
         for ($i = 1; $i <= $formParams['itemAmount']; $i++) { 
          if (!in_array($i, $givenShelf)) { 
           $child = new Child(); 
           $child->setParent($parent); 
           $child->setCupboard($formParams['cupboard']); 
           $child->setShelf($formParams['shelf']); 
           $child->setItem($i); 
    
           $em->persist($child); 
           $em->flush(); 
          } 
         } 
         return new RedirectResponse($this->admin->generateUrl('show', array('id' => $parent->getId()))); 
        } 
    
        return $this->render('AppBundle:Parent:add_childs.html.twig', array(
         'form' => $form->createView(), 
         'parent' =>$parent, 
        )); 
    } 
    

    ekstra bilgi için bu benim form oluşturucu görünür:

    public function buildForm(FormBuilderInterface $builder, array $options) { 
        $builder 
         ->add('cupboard', NumberType::class) 
         ->add('shelf', NumberType::class) 
         ->add('itemAmount', NumberType::class, array('label' => 'Number of Items')) 
        ; 
    } 
    

    nasıl yapmak gerçeği ile mümkün olduğunca bu eylem gibi basit yapabilirsiniz Ebeveyn için bir dolaptaki bir rafa sadece benzersiz eşyalar eklendiğinden emin olun. Özellikleri ve sınıfları değiştiremiyorum. Bununla çalışmak zorundayım. Herhangi bir dinleyici ya da işlev oluşturana kadar herhangi bir karmaşık yol kullanmak istemiyorum.

    Umarım benim durumumu iyi açıklamış olurum ve umarım birileri bana iyi geribildirim konusunda yardımcı olabilir.

  • cevap

    4

    Sen böyle Parent sınıfın addChild fonksiyonunu değiştirebileceğiniz doğru:

    /** 
        * Add child 
        * 
        * @param \AppBundle\Entity\Child $child 
        * 
        * @return Parent 
        */ 
        public function addChild(Child $child) 
        { 
         if (! is_array($this->childs) || ! in_array($child, $this->childs)) { 
          $this->childs[] = $child; 
          $child->setParent($this); 
         } 
         return $this; 
        } 
    

    Bu koşullu basitçe hiçbir çocuk henüz yoksa çocuk zaten değilse, çocuğu ekleyebilir veya belirtiyor $this->childs dizisinde ekleyin.

    +1

    Bilgim in_array işlevi, nesneleri karşılaştırılamıyor – michelek

    1

    Bir Doktrin koleksiyon olarak removeChild aracılığıyla $childs erişim Çünkü:

    /** 
    * Remove child 
    * 
    * @param \AppBundle\Entity\Child $child 
    */ 
    public function removeChild(\AppBundle\Entity\Child $child) 
    { 
        $this->childs->removeElement($child); 
    } 
    

    Yani, yapıcı içinde, öncelikle oğul toplama başlatmak gerekir.

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

    Yinelenen çocukları önlemek için, koleksiyona eklemeden önce mevcut denetimleri yapmanız gerekir.

    /** 
    * Add child 
    * 
    * @param \AppBundle\Entity\Child $child 
    * 
    * @return Parent 
    */ 
    public function addChild(\AppBundle\Entity\Child $child) 
    { 
        if (!$this->childs->contains($child)) { 
         $this->childs->add($child); 
         $child->setParent($this); 
        } 
    
        return $this; 
    }