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”,那么结果会是这样的: