SF3+Doctrine 计算日期之间的价格
SF3+Doctrine calculate price between dates
所以在我的 Symfony 3 项目中,我需要创建一种带有 3 个参数 的价格计算器:date_from , date_to, guest_number。 Table 在 MySql 中看起来像:
-----------------------------------------------------------------
id | date_from | date_to | people | price
-----------------------------------------------------------------
1 | 2016-01-15 | 2016-04-20 | 1 | 100
-----------------------------------------------------------------
2 | 2016-04-20 | 2016-08-15 | 1 | 200
-----------------------------------------------------------------
3 | 2016-04-20 | 2016-08-15 | 2 | 250
例如,某位客人选择2016-01-01至2016-01-10。计算器应该 return 1000。为此
创建 SQL 语句没什么大不了的
例2,有人为1个人选择了2016-04-15到2016-04-25。
问题 是如何使用 Doctrine QueryBuilder 语句构建计算 'n' 天从一个时期乘以价格和'n'天从另一个时期乘以相应的价格?
假设您有一个实体日历:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="CalendarRepository")
* @ORM\Table(name="calendar")
*/
class Calendar
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="date")
*/
private $dateFrom;
/**
* @ORM\Column(type="date")
*/
private $dateTo;
/**
* @ORM\Column(type="integer")
*/
private $people;
/**
* @ORM\Column(type="integer")
*/
private $price;
}
那么您的存储库 class 可能如下所示:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class CalendarRepository extends EntityRepository
{
public function findPriceFor(\DateTime $dateFrom, \DateTime $dateTo, $nrOfPeople)
{
$qb = $this->createQueryBuilder('calendar');
$qb->select('SUM(
CASE
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, calendar.dateFrom)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, :dateFromChosen)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, :dateFromChosen)
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, calendar.dateFrom)
ELSE 0
END
)*calendar.price AS intervalPrice');
$qb->andWhere('calendar.people = :nrOfPeople')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lt('calendar.dateFrom', ':dateToChosen'),
$qb->expr()->gt('calendar.dateTo', ':dateFromChosen')
)
);
$qb->setParameter('nrOfPeople', $nrOfPeople)
->setParameter('dateFromChosen', $dateFrom->format('Y-m-d'))
->setParameter('dateToChosen', $dateTo->format('Y-m-d'));
$qb->groupBy('calendar.id');
$query = $qb->getQuery();
$resultArray = $query->execute();
$totalPrice = array_sum(array_column($resultArray, 'intervalPrice'));
return $totalPrice;
}
}
如果我们以您的示例 MySQL table 为例,并决定计算 1 人的价格,从“2016-04-15”到“2016-04-25”,那么结果会是这样的:
所以在我的 Symfony 3 项目中,我需要创建一种带有 3 个参数 的价格计算器:date_from , date_to, guest_number。 Table 在 MySql 中看起来像:
-----------------------------------------------------------------
id | date_from | date_to | people | price
-----------------------------------------------------------------
1 | 2016-01-15 | 2016-04-20 | 1 | 100
-----------------------------------------------------------------
2 | 2016-04-20 | 2016-08-15 | 1 | 200
-----------------------------------------------------------------
3 | 2016-04-20 | 2016-08-15 | 2 | 250
例如,某位客人选择2016-01-01至2016-01-10。计算器应该 return 1000。为此
创建 SQL 语句没什么大不了的例2,有人为1个人选择了2016-04-15到2016-04-25。
问题 是如何使用 Doctrine QueryBuilder 语句构建计算 'n' 天从一个时期乘以价格和'n'天从另一个时期乘以相应的价格?
假设您有一个实体日历:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="CalendarRepository")
* @ORM\Table(name="calendar")
*/
class Calendar
{
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="date")
*/
private $dateFrom;
/**
* @ORM\Column(type="date")
*/
private $dateTo;
/**
* @ORM\Column(type="integer")
*/
private $people;
/**
* @ORM\Column(type="integer")
*/
private $price;
}
那么您的存储库 class 可能如下所示:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\EntityRepository;
class CalendarRepository extends EntityRepository
{
public function findPriceFor(\DateTime $dateFrom, \DateTime $dateTo, $nrOfPeople)
{
$qb = $this->createQueryBuilder('calendar');
$qb->select('SUM(
CASE
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, calendar.dateFrom)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo >= :dateToChosen THEN DATE_DIFF(:dateToChosen, :dateFromChosen)
WHEN calendar.dateFrom <= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, :dateFromChosen)
WHEN calendar.dateFrom >= :dateFromChosen AND calendar.dateTo <= :dateToChosen THEN DATE_DIFF(calendar.dateTo, calendar.dateFrom)
ELSE 0
END
)*calendar.price AS intervalPrice');
$qb->andWhere('calendar.people = :nrOfPeople')
->andWhere(
$qb->expr()->andX(
$qb->expr()->lt('calendar.dateFrom', ':dateToChosen'),
$qb->expr()->gt('calendar.dateTo', ':dateFromChosen')
)
);
$qb->setParameter('nrOfPeople', $nrOfPeople)
->setParameter('dateFromChosen', $dateFrom->format('Y-m-d'))
->setParameter('dateToChosen', $dateTo->format('Y-m-d'));
$qb->groupBy('calendar.id');
$query = $qb->getQuery();
$resultArray = $query->execute();
$totalPrice = array_sum(array_column($resultArray, 'intervalPrice'));
return $totalPrice;
}
}
如果我们以您的示例 MySQL table 为例,并决定计算 1 人的价格,从“2016-04-15”到“2016-04-25”,那么结果会是这样的: