我有两个实体
User
和CalendarEvent
。我的用户附属于一家工厂,calendarEvent 可用于了解用户是否被“借用”到他所属工厂的另一家工厂...
我的两个实体是这样的:
用户:
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(name="firstname", type="string", length=255, nullable=true)
*/
private $firstname;
/**
* @var string
* @ORM\Column(name="lastname", type="string", length=255, nullable=true)
*/
private $lastname;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\CalendarEvent", mappedBy="user")
*/
private $events;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Factory", inversedBy="users")
* @ORM\JoinColumn(name="factory_id", referencedColumnName="id")
*/
private $factory;
}
日历事件:
class CalendarEvent
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var \DateTime
* @ORM\Column(type="datetime", name="event_start")
*/
private $startDate;
/**
* @var \DateTime
* @ORM\Column(type="datetime", name="event_end")
*/
private $endDate;
/**
* @var bool
* @ORM\Column(name="isLoan", type="boolean")
*/
private $isLoan = TRUE;
/**
* @ORM\ManyToOne(targetEntity="Factory")
* @ORM\JoinColumn(name="factory_id", referencedColumnName="id", nullable = true)
*/
private $factory;
/**
* @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="events")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
}
我想做的是在
UserRepository
中创建一个存储库函数,当我在条目参数中使用工厂触发请求时,它会告诉我实际上是工厂的人...
为了实现这一目标,我尝试指定一个条件。这种情况应该是这样的:
select * from user where (
(user.factory == $idfactory AND not loaned_to_other_factory) OR
(user.factory != $idfactory AND loaned_to_my_factory)
)
要知道用户是否已被借用到我的工厂,必须验证以下条件:
Does a record exist in CalendarEvent where startDate < NOW and endDate > NOW and loaned == true and factory == $factory
我正在尝试使用我的存储库来使用用户和/或条件,但我已经被该查询困扰了很长时间,我什至不习惯使用存储库,因为 findBy 方法在大多数情况下都可以正常工作。 .
我尝试了这个,但这个变量有一个错误
Expression of type 'Doctrine\ORM\QueryBuilder' not allowed in this context.
$notLoanedToOther
:
public function findByFactory($idFactory)
{
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->leftJoin('u.events', 'e');
$sub = $this->createQueryBuilder("e");
$sub->select("e");
$sub->from("CalendarEvent","e");
$sub->where('e.user = u.id');
$sub->andWhere('e.startDate < :now');
$sub->andWhere('e.endDate > :now');
$notLoanedToOther = $qb->where($qb->expr()->not($qb->expr()->exists($sub->getDQL())));
$sub = $this->createQueryBuilder("e");
$sub->select("e");
$sub->from("CalendarEvent","e");
$sub->where('e.user = u.id');
$sub->where('e.factory = :idf');
$sub->andWhere('e.startDate < :now');
$sub->andWhere('e.endDate > :now');
$loanedToMyFactory = $qb->where($qb->expr()->exists($sub->getDQL()));
$condition1 = $qb->expr()->andX(
$qb->expr()->eq('u.factory', ':idf'),
$notLoanedToOther
);
$condition2 = $qb->expr()->andX(
$qb->expr()->neq('u.factory', ':idf'),
$loanedToMyFactory
);
$qb ->where($qb->expr()->orX($condition1, $condition2));
$qb ->setParameter('idf', $idFactory);
return $qb->getQuery()->getResult();
}
我真的希望我说得有道理,有人可以给我一些建议来实现这一目标。预先感谢
我想你可以将你的存在查询翻译为 not in
$notLoanedToOther = $this->createQueryBuilder('e')
->select('e.user')
->from('CalendarEvent', 'e')
->andWhere('e.startDate < :now')
->andWhere('e.endDate > :now')
->getDQL();
$loanedToMyFactory = $this->createQueryBuilder('e')
->select('e.user')
->from('CalendarEvent', 'e')
->where('e.factory = :idf')
->andWhere('e.startDate < :now')
->andWhere('e.endDate > :now')
->getDQL();
$qb = $this->_em->createQueryBuilder();
$qb->select('u')
->from($this->_entityName, 'u')
->where(
$qb->expr()->not(
$qb->expr()->in(
'u.id',
$notLoanedToOther
)
)
)
->andWhere(
$qb->expr()->in(
'u.id',
$loanedToMyFactory
)
)
->where(
$qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->eq('u.factory', ':idf'),
$qb->expr()->not(
$qb->expr()->in(
'u.id',
$notLoanedToOther
)
)
),
$qb->expr()->andX(
$qb->expr()->neq('u.factory', ':idf'),
$qb->expr()->in(
'u.id',
$loanedToMyFactory
)
)
)
)
->setParameter('idf', $idFactory)
->setParameter('now', $someDate);
如何根据您在 SQL 中指定的条件,使用带有联接的简单 DQL 查询而不是复杂的 not in 子句
从用户中选择*,其中( (user.factory == $idfactory 并且不借给其他工厂) 或者 (user.factory != $idfactory AND 借用_to_my_factory) )
您可以在 DQL 中将其等效编写为
SELECT u
FROM User u
LEFT JOIN u.events nl WITH e.startDate < :now AND e.endDate > :now
LEFT JOIN u.events l WITH e.startDate < :now AND e.endDate > :now AND e.factory = :idf
WHERE (
u.factory = :idf AND nl.id IS NULL
) OR (
u.factory != :idf AND l.id IS NOT NULL
)
使用附加条款与用户加入事件实体两次,一个用于借出,另一个用于未加载,然后应用您的条件,我添加了
IS NULL
和 IS NOT NULL
过滤器来满足您的存在和不存在条件