Symfony Form + File Collection + oTm-mTo = сохраненные файлы всегда удаляются при обновлении владельца - PullRequest
0 голосов
/ 29 декабря 2018

У меня есть сущность Item и сущность File

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

Удаление происходит на $form->handleRequest($request); Я пытался сбрасывать данные до и после и могу подтвердить 100%удаление происходит там.

Мой $itemEntity затем предварительно заполняется существующими файлами, но исчезает после handleRequest в $form

Я также использую метод addвместо set и с arrayCollection в моей сущности

Я заглянул в профилировщик и увидел, что происходит запрос на удаление доктрины SQL

Мне кажется, это очень странное поведение;Я не удалял элемент, и у меня даже нет orphanRemoval или cascade{delete}.

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

вопрос на миллион долларов?

КОНТРОЛЛЕР

  $itemEntity = $em->getRepository(Item::class)->findOneBy([
       'uid' => $uid,
  ]);

  // create form
  $form = $this->createForm(NewItemType::class, $itemEntity);

  // if I dump Item Entity here I can see my old files
  $form->handleRequest($request);
  // if I dump Item Entity here they are gone and replaced by the new   ones

  // .... later but never reached
  $item->addFile($fileInstance);

СУЩНОСТЬ ЭЛЕМЕНТА:

/**
 * @ORM\OneToMany(targetEntity="App\Entity\File", mappedBy="item", cascade={"persist"})
 */
private $file;

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

СУЩНОСТЬ ФАЙЛА:

/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $id;

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

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\Item", inversedBy="file")
 * @ORM\JoinColumn(nullable=false)
 */
private $item;

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

/**
 * @ORM\Column(type="integer")
 */
private $type;

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

/**
 * @ORM\Column(type="integer", nullable=true)
 */
private $position;

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

/**
 * @var UploadedFile|null
 */
protected $file;


public function getFile(): ?UploadedFile
{
    return $this->file;
}


public function setFile(UploadedFile $file): void
{
    $this->file = $file;
}

public function getId(): ?int
{
    return $this->id;
}

public function getPath(): ?string
{
    return $this->path;
}

public function setPath(string $path): self
{
    $this->path = $path;

    return $this;
}

public function getUid(): ?string
{
    return $this->uid;
}

public function setUid(string $uid): self
{
    $this->uid = $uid;

    return $this;
}

public function getItem(): ?Item
{
    return $this->item;
}

public function setBike(?Item $item): self
{
    $this->item = $item;

    return $this;
}

public function getType(): ?int
{
    return $this->type;
}

public function setType(int $type): self
{
    $this->type = $type;

    return $this;
}

public function getDescription(): ?string
{
    return $this->description;
}

public function setDescription(?string $description): self
{
    $this->description = $description;

    return $this;
}

public function getPosition(): ?int
{
    return $this->position;
}

public function setPosition(?int $position): self
{
    $this->position = $position;

    return $this;
}

public function getMain(): ?bool
{
    return $this->main;
}

public function setMain(?bool $main): self
{
    $this->main = $main;

    return $this;
}

ТИП СБОРА ФОРМЫ

->add('item', CollectionType::class, array(
     'label' => false,
     'entry_type' => ItemFileType::class,
     'error_bubbling' => false,
     'entry_options' => [ 'required' => false, 'error_bubbling' => true ],
     'allow_add' => true,
     'allow_delete' => true
 ))

ФАЙЛ ПУНКТАТИП

->add('file', FileType::class, [
     'label' => false,
     'required' => false
   ])

->add('description')

->add('main', CheckboxType::class,[
        'label'    => 'Make this one the main picture',
        'required' => false,
]);

1 Ответ

0 голосов
/ 29 декабря 2018

Это обычная ситуация, когда дело доходит до ArrayCollection.Прежде всего, у вас есть $file переменная в Item сущности

/**
 * @ORM\OneToMany(targetEntity="App\Entity\File", mappedBy="item", cascade={"persist"})
 */
private $file;

Фактически, лучше назвать эту переменную $files, если возможно прикрепить пару или более файлов к одномуitem.

И в вашем коде также должна быть следующая строка

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

Проблема здесь в том, что когда вы вызываете handleRequest, он полностью переписывает ваше свойство $files.Как я думаю, это происходит потому, что у вас есть только set метод в вашей Item сущности, в то время как у вас не должно быть метода set, но add и remove

public function addFile(File $file)
{
    if (!$this->files->contains($file)) {
        $file->setItem($this);
        $this->files->add($file);
    }

    return $this;
}

public function removeFile(File $file)
{
    $this->files->removeElement($file);

    return $this;
}

Дело не в томполностью переписать ArrayCollection, но расширить его.Если вы удалите какой-либо элемент из коллекции, Doctrine удалит его из базы данных.

К вашему сведению Это также может произойти из-за того, что коллекция $files не была предварительно заполнена существующей коллекцией перед отправкой формы

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