Jack Brummer Ответов: 1

Добавляйте дочерние объекты к родительским только в том случае, если они еще не существуют


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

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

Я использую Symfony и Doctrine, и мой базовый родительский класс выглядит следующим образом:

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


Мой детский класс выглядит так (опять же очень просто):

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


Затем у меня есть действие для каждого родительского объекта (вроде того же, что и действие редактирования), которое должно создавать для него дочерних объектов. Когда я нажимаю на ссылку (для конкретного родителя), создается форма с тремя полями ввода:

- Буфет
- Полка
- Количество предметов

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

Как я могу сделать это как можно проще? Я понимаю, что могу использовать функцию addChild из родительского класса, но не знаю, как это сделать.

Что я уже пробовал:

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

Это мой код:

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,
    ));
}


Для получения дополнительной информации, вот как выглядит мой конструктор форм:

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'))
    ;
}


Как я могу сделать это действие как можно более простым с тем, чтобы убедиться, что только уникальные предметы добавляются на полку в шкафу для родителей. Я не могу изменить ни свойства, ни классы. Я должен работать с этим. Я не хочу использовать какой-либо другой сложный способ, такой как создание каких-либо слушателей или других функций until.

Я надеюсь, что хорошо объяснил свою ситуацию, и я надеюсь, что кто-то может помочь мне с хорошей обратной связью.

1 Ответов

Рейтинг:
0

Patrice T

Цитата:
Добавляйте дочерние объекты к родительским только в том случае, если они еще не существуют

Единственное решение - проверить, существует ли дочерний объект перед добавлением.

try to find children object
is not exist
   add children object
endif