Как удалить «обратную сторону» с двумя отношениями - PullRequest
0 голосов
/ 06 апреля 2019

Существует двусторонняя связь между продажей, складом и каталогом. Продажи и акции, должны иметь запись в каталоге. Но это Это не всегда так в данный момент ... Так что отношения «обнуляются».

class Sale {

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Stock", inversedBy="sales")
     */
    private $stock;

    public function getCatalog(): ?Catalog
    {
        return $this->catalog;
    }

    public function setCatalog(?Catalog $catalog): self
    {
        $this->catalog = $catalog;

        return $this;
    }
}

class Stock
{
    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Catalog", inversedBy="stock")
     */
    private $catalog;

    public function getCatalog(): ?Catalog
    {
        return $this->catalog;
    }

    public function setCatalog(?Catalog $catalog): self
    {
        $this->catalog = $catalog;

        return $this;
    }
}

class Catalog
{
    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Sale", mappedBy="catalog")
     */
    private $sales;

    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Stock", mappedBy="catalog")
     */
    private $stock;

    public function addSale(Sale $sale): self
    {
        if (!$this->sales->contains($sale)) {
            $this->sales[] = $sale;
            $sale->setCatalog($this);
        }

        return $this;
    }

    public function removeSale(Sale $sale): self
    {
        if ($this->sales->contains($sale)) {
            $this->sales->removeElement($sale);
            // set the owning side to null (unless already changed)
            if ($sale->getCatalog() === $this) {
                $sale->setCatalog(null);
            }
        }

        return $this;
    }

    public function getStock(): ?Stock
    {
        return $this->stock;
    }

    public function setStock(?Stock $stock): self
    {
        $this->stock = $stock;

        // set (or unset) the owning side of the relation if necessary
        $newCatalog = $stock === null ? null : $this;
        if ($newCatalog !== $stock->getCatalog()) {
            $stock->setCatalog($newCatalog);
        }

        return $this;
    }
}

Все это автоматически генерируется в Symfony с make: entity. При организации Каталог, также необходимо удалить записи каталога.

class CatalogController extends AbstractController 
{

    /**
     * @Route(
     *     path    = "/catalog-delete/{id<[1-9]\d*>}",
     *     name    = "catalog_delete",
     *     methods = {"GET"}
     * )
     */
    public function delete(int $id)
    {
        // get catalog
        $catalog = $this->catalogRepository->find($id);
        if (!$catalog) {
            throw $this->createNotFoundException($this->translator->trans('system.error.notfound') . $id);
        }

        // delete
        $this->entityManager->remove($catalog);
        $this->entityManager->flush();

        return $this->redirectToRoute('catalog_list');
    }
}

Пока все довольно просто. Но как удалить ассоциации, не удаляя какие акции или продажи? Я получаю здесь такие ошибки (без удаления ассоциаций)

Cannot delete or update a parent row: a foreign key constraint fails (`symfony`.`sale`, CONSTRAINT `FK_E54BC005DCD6110` FOREIGN KEY (`stock_id`) REFERENCES `stock` (`id`))

или как

Call to a member function getCatalog() on null

Когда я пытаюсь внутри функции delete ();)

$catalog->setStock(null);
foreach($catalog->getSales() as $sale) {
    $catalog->getSales()->removeElement($sale); // ????????
}

Я могу использовать DQL, чтобы установить category_id в Продажи и Запас на ноль (ОБНОВЛЕНИЕ продажи / НАБОР НАСТРОЙКИ category_id = ноль ГДЕ category_id = X). Но я думаю, что это не обычный «нормальный путь».

Для этого случая автоматически сгенерированная функция для меня немного утомительна Также документация доктрины здесь https://www.doctrine -project.org / проекты / Доктрина-ОРМ / ы / 2,6 / ссылки / рабочий-с associations.html # удаление-ассоциации

Я читал, что только ассоциация несет ответственность за но как мне включить в мою функцию Stock и все продажи, если они есть?

Извините за длинный вопрос и основную тему.

Спасибо и наилучшими пожеланиями


Мои Вопросы были помечены как дубликаты. Основное отличие -

Я хотел бы знать в своем вопросе, как реализовать вызовы функций для установки собственных объектов (двух или нескольких) на ноль. Процесс удаления. Какая сущность, какие звонки. Только добавление

@ORM\JoinColumn(name="catalog_id", referencedColumnName="id", onDelete="SET NULL")  

(старый ответ) не решить проблему.

--------- Временное решение DQL ----------


// Controller

/**
 * @Route(
 *     path    = "/catalog-delete/{id<[1-9]\d*>}",
 *     name    = "catalog_delete",
 *     methods = {"GET"}
 * )
 */
public function delete(int $id)
{
    // get catalog
    $numDeleted = $this->catalogRepository->delete($id);
    if (!$numDeleted) {
        throw $this->createNotFoundException($this->translator->trans('system.error.notfound') . $id);
    }

    return $this->redirectToRoute('catalog_list');
}

// Repository

/**
 * Delete with associations
 */
public function delete(int $id): int
{
    $this->getEntityManager()
        ->createQuery(/** @lang DQL */'
            UPDATE App\Entity\Sale s 
               SET s.catalog = NULL
             WHERE s.catalog = :id 
        ')
        ->setParameter('id', $id)
        ->execute()
    ;

    $this->getEntityManager()
        ->createQuery(/** @lang DQL */'
            UPDATE App\Entity\Stock s 
               SET s.catalog = NULL
             WHERE s.catalog = :id 
        ')
        ->setParameter('id', $id)
        ->execute()
    ;

    $numDeleted = $this->getEntityManager()
        ->createQuery(/** @lang DQL */'
            DELETE FROM App\Entity\Catalog c
                  WHERE c.id = :id 
        ')
        ->setParameter('id', $id)
        ->execute()
    ;

    return $numDeleted;
}

мой самый длинный пост;)

1 Ответ

0 голосов
/ 07 апреля 2019

Решение - это действительно простая установка. это также может быть однонаправленное отношение.

class Sale {

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Stock")
     * @ORM\JoinColumn(onDelete="SET NULL")
     */
    private $stock;

    public function getCatalog(): ?Catalog
    {
        return $this->catalog;
    }

    public function setCatalog(?Catalog $catalog): self
    {
        $this->catalog = $catalog;

        return $this;
    }
}

class Stock
{
    /**
     * @ORM\OneToOne(targetEntity="App\Entity\Catalog")
     * @ORM\JoinColumn(onDelete="SET NULL")
     */
    private $catalog;

    public function getCatalog(): ?Catalog
    {
        return $this->catalog;
    }

    public function setCatalog(?Catalog $catalog): self
    {
        $this->catalog = $catalog;

        return $this;
    }
}

class Catalog
{

}

Функция контроллера тогда работает хорошо. Вчера я перепробовал слишком много вещей ...

...