Symfony\Doctrine createQueryBuilder() select 'not in' 来自 OneToMany 关系
Symfony\Doctrine createQueryBuilder() select 'not in' from a OneToMany relation
我有三个实体:奖杯 |比赛 |赛季
为一个赛季的一个奖杯创建一个比赛(你不能有两个具有相同组合的比赛"season + trophy")。
作为与 Trophy 的 ManyToOne 关系以及与 Season 的 ManyToOne 关系的竞争。
奖杯和赛季没有直接关系
我想在一个页面上显示两个下拉菜单,其中第二个下拉菜单的内容依赖于第一个下拉菜单的值:
第一个下拉菜单允许 select 奖杯类型(这是奖杯实体的 属性),第二个下拉菜单必须列出 "still available" 奖杯类型 selected 的季节(意思是"list all seasons for which there are no competition for this trophy type")
我几乎完成了所有工作(Formtype 中的侦听器,ajax 等)我在 SeasonRepository 中创建了一个特定函数 allWithoutThisCompetitionType()。每次用户 select 下拉菜单中的新值时都会正确调用函数但是...我对 SQL 和 dql 一无所知,所以我正在努力为我的查询找到正确的公式.我尝试过使用 notin(),使用 "sub" 或 "nested" 查询...我绝对不知道我在做什么...
我怎样才能做类似的事情? :
$qb = $em->getRepository(\App\Entity\Seasonmanager\Season::class)->createQueryBuilder('s')
->where('s.competitions.trophy != :trophy')
->setParameter('trophy', $trophy);
=这里是所有没有用这个奖杯创建比赛的赛季
感谢您的帮助。
奖杯实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\TrophyRepository")
*/
class Trophy
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $uniqueid;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\OneToMany(targetEntity="App\Entity\Seasonmanager\Competition", mappedBy="trophy", orphanRemoval=true)
*/
private $competitions;
竞赛实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\CompetitionRepository")
* @UniqueEntity(
* fields={"trophy","season"},
* errorPath="trophy",
* message="Une compétition existe déjà pour ce trophée et cette saison"
* )
*/
class Competition
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Seasonmanager\Trophy", inversedBy="competitions")
* @ORM\JoinColumn(nullable=false)
*/
private $trophy;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Seasonmanager\Season", inversedBy="competitions")
* @ORM\JoinColumn(nullable=false)
*/
private $season;
季节实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\SeasonRepository")
* @UniqueEntity("yearin")
*/
class Season
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer", length=4)
*/
private $yearout;
/**
* @ORM\Column(type="string", length=8)
*/
private $uniqueid;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\OneToMany(targetEntity="App\Entity\Seasonmanager\Competition", mappedBy="season", orphanRemoval=true)
*/
private $competitions;
我尝试添加查询的 SeasonRepository :
namespace App\Repository\Seasonmanager;
use App\Entity\Seasonmanager\Season;
use App\Entity\Seasonmanager\Trophy;
use App\Entity\Seasonmanager\Competition;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
/**
* @method Season|null find($id, $lockMode = null, $lockVersion = null)
* @method Season|null findOneBy(array $criteria, array $orderBy = null)
* @method Season[] findAll()
* @method Season[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SeasonRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Season::class);
}
public function allWithoutThisCompetitionType($type): array
{
$em = $this->getEntityManager();
$trophys = $em
->getRepository(Trophy::class)
->findBy(['uniqueid' => $type],['id'=>'DESC'])
;
$trophy = reset($trophys);
$qb = $em->getRepository(\App\Entity\Seasonmanager\Season::class)->createQueryBuilder('s')
->where('s.competitions.trophy', $trophy);
$query = $qb->getQuery();
$result = $query->getResult();
$donnees = $result;
return $donnees;
}
这是查询,但我不能 100% 确定它会满足您的需要。
如果有什么不对的地方,请在评论中告诉我,我会编辑我的答案。
public function allWithoutThisCompetitionType($trophy) {
// Split init from the rest of the query in case you need to use `$qb->expr()`
$qb=$this->createQueryBuilder("season");
$qb->leftJoin("season.competition", "competition") // Join competition
->join("competition.trophy", "trophy") // Join Trophy
->andWhere($qb->expr()->orX( // Or (either one of the following satements)
$qb->expr()->isNull("competition.id"),
$qb->expr()->notIn("trophy.uniqueid", ":trophy")))
->setParameter("trophy", $trophy);
return $qb->getQuery()->getResult();
}
我有三个实体:奖杯 |比赛 |赛季
为一个赛季的一个奖杯创建一个比赛(你不能有两个具有相同组合的比赛"season + trophy")。
作为与 Trophy 的 ManyToOne 关系以及与 Season 的 ManyToOne 关系的竞争。
奖杯和赛季没有直接关系
我想在一个页面上显示两个下拉菜单,其中第二个下拉菜单的内容依赖于第一个下拉菜单的值: 第一个下拉菜单允许 select 奖杯类型(这是奖杯实体的 属性),第二个下拉菜单必须列出 "still available" 奖杯类型 selected 的季节(意思是"list all seasons for which there are no competition for this trophy type")
我几乎完成了所有工作(Formtype 中的侦听器,ajax 等)我在 SeasonRepository 中创建了一个特定函数 allWithoutThisCompetitionType()。每次用户 select 下拉菜单中的新值时都会正确调用函数但是...我对 SQL 和 dql 一无所知,所以我正在努力为我的查询找到正确的公式.我尝试过使用 notin(),使用 "sub" 或 "nested" 查询...我绝对不知道我在做什么...
我怎样才能做类似的事情? :
$qb = $em->getRepository(\App\Entity\Seasonmanager\Season::class)->createQueryBuilder('s')
->where('s.competitions.trophy != :trophy')
->setParameter('trophy', $trophy);
=这里是所有没有用这个奖杯创建比赛的赛季
感谢您的帮助。
奖杯实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\TrophyRepository")
*/
class Trophy
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $uniqueid;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\OneToMany(targetEntity="App\Entity\Seasonmanager\Competition", mappedBy="trophy", orphanRemoval=true)
*/
private $competitions;
竞赛实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\CompetitionRepository")
* @UniqueEntity(
* fields={"trophy","season"},
* errorPath="trophy",
* message="Une compétition existe déjà pour ce trophée et cette saison"
* )
*/
class Competition
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Seasonmanager\Trophy", inversedBy="competitions")
* @ORM\JoinColumn(nullable=false)
*/
private $trophy;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Seasonmanager\Season", inversedBy="competitions")
* @ORM\JoinColumn(nullable=false)
*/
private $season;
季节实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\Seasonmanager\SeasonRepository")
* @UniqueEntity("yearin")
*/
class Season
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer", length=4)
*/
private $yearout;
/**
* @ORM\Column(type="string", length=8)
*/
private $uniqueid;
// other properties here...
//////////////////////////////////////////////////////////////////////////////////
//// LIAISONS VERS D'AUTRES ENTITY ////
/**
* @ORM\OneToMany(targetEntity="App\Entity\Seasonmanager\Competition", mappedBy="season", orphanRemoval=true)
*/
private $competitions;
我尝试添加查询的 SeasonRepository :
namespace App\Repository\Seasonmanager;
use App\Entity\Seasonmanager\Season;
use App\Entity\Seasonmanager\Trophy;
use App\Entity\Seasonmanager\Competition;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
/**
* @method Season|null find($id, $lockMode = null, $lockVersion = null)
* @method Season|null findOneBy(array $criteria, array $orderBy = null)
* @method Season[] findAll()
* @method Season[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class SeasonRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Season::class);
}
public function allWithoutThisCompetitionType($type): array
{
$em = $this->getEntityManager();
$trophys = $em
->getRepository(Trophy::class)
->findBy(['uniqueid' => $type],['id'=>'DESC'])
;
$trophy = reset($trophys);
$qb = $em->getRepository(\App\Entity\Seasonmanager\Season::class)->createQueryBuilder('s')
->where('s.competitions.trophy', $trophy);
$query = $qb->getQuery();
$result = $query->getResult();
$donnees = $result;
return $donnees;
}
这是查询,但我不能 100% 确定它会满足您的需要。
如果有什么不对的地方,请在评论中告诉我,我会编辑我的答案。
public function allWithoutThisCompetitionType($trophy) {
// Split init from the rest of the query in case you need to use `$qb->expr()`
$qb=$this->createQueryBuilder("season");
$qb->leftJoin("season.competition", "competition") // Join competition
->join("competition.trophy", "trophy") // Join Trophy
->andWhere($qb->expr()->orX( // Or (either one of the following satements)
$qb->expr()->isNull("competition.id"),
$qb->expr()->notIn("trophy.uniqueid", ":trophy")))
->setParameter("trophy", $trophy);
return $qb->getQuery()->getResult();
}