PHP - Doctrine - копировать дерево - использовать значения полей @id для установки полей, помеченных как отношения - PullRequest
0 голосов
/ 29 января 2020

Упрощенно, у меня есть эта таблица:

tree_table
--------------------
id|root_id|parent_id
1 |null  |null
2 |1     |1
3 |2     |1

Для этого у меня есть эта сущность:


namespace StackOverflow;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="tree_table")
 */
class TreeTable {

  /**
   * @ORM\Column(name="id", type="bigint", nullable=false)
   * @ORM\Id
   */
  public id;

  /**
   * @ORM\OneToOne(targetEntity="StackOverflow\TreeTable")
   * @ORM\JoinColumn(name="root_id", referencedColumnName="id")
   */
  public root;

  /**
   * @ORM\OneToOne(targetEntity="StackOverflow\TreeTable")
   * @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
   */
  public parent;
}

Я пытаюсь скопировать дерево из этой таблицы. Я могу легко выбрать все дерево, сказав WHERE root_id = :rootId OR id = :rootId. Но при копировании я должен изменить родительские идентификаторы.

Я вижу каноническое решение, в котором я просто говорю что-то вроде этого:

foreach ($trees as $treePart) {
  $newTreePart = new TreeTable();
  $this->copyNeededThings($treePart, $newTreePart); // copies information that I want to have copied

  /**
   * Find the corresponding new parent and add it to this newTreePart by calling
   * $newTreepart->parent = $thatNewParent
   */
  $this->addToParent($treePart, $newTreePart); 
}

Но, делая это таким образом, я должен сохраняйте все дерево в памяти, и я боюсь, что мне быстро не хватит памяти. Я бы предпочел сделать два разбора по дереву. В первом разборе я создам все новые деревья, но оставлю родителей такими, какими они были изначально. И я создам карту, сопоставляя оригинальные идентификаторы сущностей с новыми идентификаторами. Во второй части я буду использовать карту, чтобы установить идентификаторы. Это позволило бы разбить эту процедуру на страницы.

Но я не знаю, как установить внешний ключ через ключ напрямую через doctrine. Создать второй файл сущности для той же таблицы? Должен ли я добавить столбцы непосредственно к этой сущности и иметь отношение и столбец в одной таблице. Я думаю, что я мог бы также просто создать сущности TreeTable в качестве контейнера данных для идентификатора, но я беспокоюсь, что в будущем кто-то может добавить каскадное сохранение, а затем это будет неправильно понято как обновления базы данных.

Есть ли хороший, чистое решение для этой проблемы?

...