为什么我的多对多关系在 Doctrine 和 Symfony 中不起作用?

问题描述 投票:0回答:1

我的多对多关系定义如下:

两个相关表:

CREATE TABLE `homily` (
  `homilyID` int NOT NULL AUTO_INCREMENT,
  `homily` text NOT NULL,
  PRIMARY KEY (`homilyID`),
) ENGINE=InnoDB

CREATE TABLE `liturgy` (
  `liturgyID` int NOT NULL AUTO_INCREMENT,
  `timeFK` tinyint NOT NULL,
  `typeFK` tinyint NOT NULL,
  `week` tinyint NOT NULL,
  `day` tinyint NOT NULL,
  `colorFK` tinyint NOT NULL,
  `name` varchar(200) COLLATE utf8mb3_spanish_ci NOT NULL,
  PRIMARY KEY (`liturgyID`),
  UNIQUE KEY `timeFK` (`timeFK`,`typeFK`,`week`,`day`),
  KEY `colorFK` (`colorFK`)
) ENGINE=InnoDB

以及处理多对多关系的中间表:

CREATE TABLE `liturgy_homily_join` (
  `liturgyFK` int NOT NULL,
  `homilyFK` int NOT NULL,
  `theme` varchar(200) COLLATE utf8mb3_spanish_ci NOT NULL DEFAULT '',
  PRIMARY KEY (`liturgyFK`,`homilyFK`),
  KEY `homilyFK` (`homilyFK`),
  CONSTRAINT `liturgy_homily_join_ibfk_1` FOREIGN KEY (`liturgyFK`) REFERENCES `liturgy` (`liturgyID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `liturgy_homily_join_ibfk_2` FOREIGN KEY (`homilyFK`) REFERENCES `homily` (`homilyID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB

现在我想使用条件查询我的

liturgy
表并获取所有相关的
homily
行。

为此,我尝试在 Liturgy

 中表达单向多对多关系,正如文档解释的那样here

班级看起来像这样:

Liturgy

namespace App\Entity;

use App\Repository\LiturgyRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: LiturgyRepository::class)]
class Liturgy
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(name:"liturgyID")]
    private ?int $id = null;

    #[ORM\Column(type: Types::SMALLINT, name:"timeFK")]
    private ?int $timeFK = null;

    #[ORM\Column(type: Types::SMALLINT)]
    private ?int $week = null;

    #[ORM\Column(type: Types::SMALLINT)]
    private ?int $day = null;

    #[ORM\Column(length: 200)]
    private ?string $name = null;

    #[ORM\Column(type: Types::SMALLINT, name:"typeFK")]
    private ?int $typeFK = null;

    #[JoinTable(name: 'liturgy_homily_join')]
    #[JoinColumn(name: 'liturgyFK', referencedColumnName: 'id')]
    #[InverseJoinColumn(name: 'homilyFK', referencedColumnName: 'id')]
    #[ManyToMany(targetEntity: Homily::class)]

    public ?Collection $homilies=null;

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

    public function getHomilies(): ?Collection
    {
        return $this->homilies;
    }

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

    // ...

}

我还尝试了双向多对多关系,正如文档所解释的这里

在这种情况下,类看起来像这样:

Liturgy

namespace App\Entity;

use App\Repository\LiturgyRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: LiturgyRepository::class)]
class Liturgy
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(name:"liturgyID")]
    private ?int $id = null;

    #[ORM\Column(type: Types::SMALLINT, name:"timeFK")]
    private ?int $timeFK = null;

    #[ORM\Column(type: Types::SMALLINT)]
    private ?int $week = null;

    #[ORM\Column(type: Types::SMALLINT)]
    private ?int $day = null;

    #[ORM\Column(length: 200)]
    private ?string $name = null;

    #[ORM\Column(type: Types::SMALLINT, name:"typeFK")]
    private ?int $typeFK = null;
/*
    #[JoinTable(name: 'liturgy_homily_join')]
    #[JoinColumn(name: 'liturgyFK', referencedColumnName: 'id')]
    #[InverseJoinColumn(name: 'homilyFK', referencedColumnName: 'id')]
    #[ManyToMany(targetEntity: Homily::class)]
*/

    #[ManyToMany(targetEntity: Homily::class, inversedBy: 'liturgies')]
    #[JoinTable(name: 'liturgy_homily_join')]
    public ?Collection $homilies=null;

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

    public function getHomilies(): ?Collection
    {
        return $this->homilies;
    }

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

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

    public function setLiturgyID(int $liturgyID): static
    {
        $this->id = $liturgyID;
        return $this;
    }

    public function getTimeFK(): ?int
    {
        return $this->timeFK;
    }

    public function setTimeFK(int $timeFK): static
    {
        $this->timeFK = $timeFK;
        return $this;
    }

    public function getWeek(): ?int
    {
        return $this->week;
    }

    public function setWeek(int $week): static
    {
        $this->week = $week;
        return $this;
    }

    public function getDay(): ?int
    {
        return $this->day;
    }

    public function setDay(int $day): static
    {
        $this->day = $day;
        return $this;
    }

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

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

    public function getTypeFK(): ?int
    {
        return $this->typeFK;
    }

    public function setTypeFK(int $typeFK): static
    {
        $this->typeFK = $typeFK;
        return $this;
    }
}

Homily

namespace App\Entity;

use App\Repository\HomilyRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: HomilyRepository::class)]
class Homily
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(name:'homilyID')]
    private ?int $id = null;

    #[ORM\Column(type: Types::TEXT)]
    private ?string $homily = null;

    #[ManyToMany(targetEntity: Liturgy::class, mappedBy: 'homilies')]
    private Collection $liturgies;

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

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

    public function getHomily(): ?string
    {
        return $this->homily;
    }

    public function setHomily(string $homily): static
    {
        $this->homily = $homily;
        return $this;
    }

}

我的问题是,在这两种情况下,代码都不起作用。假设这段代码在

LiturgyRepository
:

public function findHomily(string $time,string $week,string $day,string $cycle): ?array
 {
     $timeFK=$this->timeAssoc[$time] ?? null;
     $day=$this->dayAssoc[$day] ?? null;
     $cycle=$this->cycleAssoc[$cycle] ?? null;
     $qb= $this->createQueryBuilder('liturgy')
     ->andWhere('liturgy.id > 0')

         /* quitamos criterios de parámetros por el momento*/
         ->setMaxResults(5)
         ->getQuery()
         ->getResult()
     ;
     dd($qb);
     return $qb;
 }

如果我理解正确,如果关系有效,我应该在

homilies
属性中包含
Homily
对象列表,但我总是得到
null
,正如您在调试中看到的:

  0 => App\Entity\Liturgy {#651 ▼
    -id: 1
    -timeFK: 1
    -week: 1
    -day: 1
    -name: "Domingo I de Adviento (Año A)."
    -typeFK: 1
    +homilies: null
  }
  1 => App\Entity\Liturgy {#649 ▼
    -id: 2
    -timeFK: 1
    -week: 2
    -day: 1
    -name: "Domingo II de Adviento (Año A)."
    -typeFK: 1
    +homilies: null

我澄清这不是数据的问题,表在这些关系中有匹配的记录。例如查询:

select 
    h.homilyID 
from liturgy l 
inner join liturgy_homily_join j 
    on l.liturgyID=j.liturgyFK 
inner join homily h 
    on j.homilyFK=h.homilyID 
where 
    l.liturgyID=1;

它给了我满足关系的所有行:

+----------+
| homilyID |
+----------+
|     1987 |
|     1989 |
|     1990 |
|     ...  |
+----------+

谁能告诉我在建立关系方面我犯了什么错误?

php symfony doctrine-orm
1个回答
0
投票

这里有一些问题!

首先,我更喜欢具有尽可能少属性的双向关系 - 您在第二个示例中显示的映射似乎不错(您可以验证学说是否满意

php bin/console doctrine:schema:validate

你的构造函数是错误的,并且将 ArrayCollection 属性赋予了错误的变量

    public function __construct() 
    {
        // Remove the $ in front of homilies !  
        $this->homilies = new ArrayCollection();
    }

那么你应该知道,集合默认是惰性的(在你尝试使用它们之前它们是未填充的)。所以只是“倾倒”你的礼拜结果不会让他们看到。

您可以通过循环检查是否有必要的结果

foreach($liturgy->getHomilies() as $homily) {...}

或者通过计数

$liturgy->getHomilies()->count()
© www.soinside.com 2019 - 2024. All rights reserved.