Доктрина один-к-одному, самореференция не работает - PullRequest
0 голосов
/ 26 июня 2018

Я работаю над унаследованным приложением, и теперь мне нужно изменить существующую таблицу (называемую категориями), чтобы в ней было поле parent_id, которое является внешним ключом первичного ключа его собственной таблицы (таблицы категорий)

У меня проблема в том, что я не могу заставить Doctrine установить родительское поле в базе данных

У меня есть следующая сущность orm:

ModelBundle\Entity\Category:
    type: entity
    table: category
    indexes:
        fki_parent_to_id:
            columns:
                - parent_id
    uniqueConstraints:
        uniq_64c19c1989d9b62:
            columns:
                - slug
        uniq_name:
            columns:
                - name
    id:
        id:
            type: integer
            nullable: false
            options:
                unsigned: false
            id: true
            generator:
                strategy: SEQUENCE
    fields:
        name:
            type: string
            nullable: false
            length: 255
            options:
                fixed: false
        slug:
            type: string
            nullable: false
            length: 255
            options:
                fixed: false
        description:
            type: string
            nullable: true
            length: 255
            options:
                fixed: false
        isActive:
            type: boolean
            nullable: false
            options:
                default: false
            column: is_active
        displayOrder:
            type: integer
            nullable: true
            options:
                unsigned: false
            column: display_order
    oneToOne:
        parent:
            targetEntity: Category
            joinColumns:
                parent_id:
                    referencedColumnName: id

    lifecycleCallbacks: {  }

Вот класс сущности:

<?php

namespace ModelBundle\Entity;

use Doctrine\Common\Collections\Collection;
use JMS\Serializer\Annotation\Expose;

use Symfony\Cmf\Bundle\SeoBundle\Extractor\TitleReadInterface;
use Symfony\Cmf\Bundle\SeoBundle\Extractor\DescriptionReadInterface;
use Symfony\Cmf\Bundle\SeoBundle\Extractor\ExtrasReadInterface;

class Category implements ExtrasReadInterface, TitleReadInterface, DescriptionReadInterface
{
    /** @var int */
    private $id;

    /** @var string */
    private $slug;

    /**
     * @Expose
     *
     * @var string
     */
    private $name;

    /** @var bool */
    protected $isActive;

    /** @var string */
    private $description;

    /** @var Collection */
    private $products;

    /** @var int */
    private $displayOrder;

    /**
     * @var Category
     */
    private $parent;


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

    public function setName(string $name): Category
    {
        $this->name = $name;
        return $this;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setIsActive(bool $isActive): Category
    {
        $this->isActive = $isActive;
        return $this;
    }

    public function getIsActive(): bool
    {
        return $this->isActive;
    }

    public function setDescription(string $description): Category
    {
        $this->description = $description;
        return $this;
    }

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

    public function __construct()
    {
        $this->products = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function addProduct(Product $products): Category
    {
        $this->products[] = $products;
        return $this;
    }

    public function removeProduct(Product $products)
    {
        $this->products->removeElement($products);
    }

    public function getProducts(): Collection
    {
        return $this->products;
    }

    public function setSlug(string $slug): Category
    {
        $this->slug = $slug;
        return $this;
    }

    public function getSlug(): string
    {
        return $this->slug ?: '';
    }

    public function getSeoTitle(): string
    {
        return $this->getName();
    }

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

    public function getSeoExtras(): array
    {
        return [
            'property' => [
                'og:title'       => $this->name,
                'og:description' => $this->description,
                'og:type'        => 'product:category'
            ],
        ];
    }

    function getDisplayOrder(): ?int
    {
        return $this->displayOrder;
    }

    public function setDisplayOrder($displayOrder): Category
    {
        $this->displayOrder = $displayOrder;
        return $this;
    }

    public function getParent() : Category
    {
        return $this->parent;
    }

    public function setParent(Category $parent): void
    {
        $this->parent = $parent;
    }

}

Это отображает то, что я сказал выше.Это похоже на то, что здесь в документации: https://www.doctrine -project.org / projects / doctrine-orm / en / 2.5 / reference / association-mapping.html # один-к-одному-самоссылке В примерах нет yaml, но я получил этот yaml из доктрины (используя команды генерации).

Независимо от того, что я делаю, я никогда не смогу сохранить то, что установлено в родительском.

Example code:

$em = $this->get('doctrine')->getManager();
$repo = $em->getRepository(Category::class);

    $newCat = new Category();
    $newCat->setName('Test11');
    $newCat->setSlug('slug1');
    $newCat->setDescription('desc1');
    $newCat->setIsActive(true);
    $newCat->setDisplayOrder(1);
    $newCat->setParent($repo->find(11)); //<-- This does not get saved in the DB

    var_dump($newCat);

    $em->persist($newCat);
    $em->flush();

$repo->find(11) возвращает объект Category, у которого есть родительский элемент (я установил его вручную в базе данных), но родительское поле имеет значение NULL.(Я также пробовал с объектом, у которого нет родителя, тот же результат) Вот переменная var_dump:

object(ModelBundle\Entity\Category)[421]
  private 'id' => null
  private 'slug' => string 'slug1' (length=42)
  private 'name' => string 'Teste11' (length=33)
  protected 'isActive' => boolean true
  private 'description' => string 'desc1' (length=5)
  private 'products' => 
    object(Doctrine\Common\Collections\ArrayCollection)[422]
      private 'elements' => 
        array (size=0)
          empty
  private 'displayOrder' => int 1
  private 'parent' => 
    object(ModelBundle\Entity\Category)[435]
      private 'id' => int 11
      private 'slug' => string 'entertaining' (length=12)
      private 'name' => string 'Browse Entertaining' (length=19)
      protected 'isActive' => boolean false
      private 'description' => string 'Selection of great food for any occasion.' (length=41)
      private 'products' => 
        object(Doctrine\ORM\PersistentCollection)[458]
          private 'snapshot' => 
            array (size=0)
          protected 'initialized' => boolean false
      private 'displayOrder' => null
      private 'parent' => null

Этот код создает новую категорию в базе данных, но родительское поле имеет значение NULL.

Что я здесь не так делаю?Что мне нужно сделать, чтобы получить это, чтобы сохранить родителя в базе данных.ПРИМЕЧАНИЕ: я не хочу oneToMany. Я просто хочу, чтобы у одной категории был один родитель, и это все.

Версии:

доктрина / аннотации v1.3.1

doctrine / cache v1.6.1

доктрина / collection v1.4.0

доктрина / common v2.7.2

доктрина / data-fixtures v1.2.2

doctrine / dbal v2.5.12

доктрина / doctrine-bundle 1.6.7

doctrine / doctrine-cache-bundle 1.3.0

doctrine / doctrine-fixtures-bundlev2.4.0

комплект доктрина / доктрина-миграция v1.2.1

доктрина / инфлектор v1.1.0

доктрина / инстанциатор 1.0.5

доктрина/ lexer v1.0.1

доктрина / миграция v1.5.0

доктрина / orm v2.5.6

oro / доктрина-расширение 1.2.0

РЕДАКТИРОВАТЬ: Извините, ребята, после 2 дней попыток заставить это работать, я заметил, что доктрина имеет следующее для кэширования (в конфигурации Symfony):

orm:
    auto_generate_proxy_classes: "%kernel.debug%"
    entity_managers:
        default:
            naming_strategy: doctrine.orm.naming_strategy.underscore
            auto_mapping: true
            metadata_cache_driver: apcu
            query_cache_driver: apcu

Как толькокак я удалил этот кеш, еввсе начало работать.Я удалял каталог кэширования вручную, но не смог увидеть, что доктрина также кэшируется с помощью apcu.

...