【问题标题】:Retrieve items by month and year with Symfony and Doctrine使用 Symfony 和 Doctrine 按月和年检索项目
【发布时间】:2016-12-22 18:52:01
【问题描述】:

我需要使用 Doctrine 检索特定类型的所有项目,其中“日期”字段存储为 DateTime。这意味着我也在使用 PHP DateTime 对象。

我需要做两件事:如果给定月份和年份,则检索该月份和年份的所有记录;如果没有给出月份和年份,则检索本月的所有记录。

我一直在研究在 Doctrine Query Builder 中使用 BETWEEN 语句,但无法弄清楚如何从“现在”创建的 PHP DateTime 对象中干净地提取月份和年份,这样 DateTime 的时间部分就不会影响查询。我也看不到将 DateTime 中日期的日期部分设置为 01 而不影响月份和年份的方法。

我认为这将是一项相当标准的任务,但找不到解决方案。任何帮助表示赞赏。

编辑:

找到了一种获取两者之间日期的 hacky 方法,但 Doctrine 返回一个空数组。使用以下代码

/**
* Returns feed for month and year
*/
public function getMonthYearFeed($month, $year)
{
 // Create two times at the start of this month and next month
$startDate = \DateTime::createFromFormat('d-n-Y',  "01-".$month."-".$year);
$startDate->setTime(0, 0 ,0);

$endDate = \DateTime::createFromFormat('d-n-Y', "01-".($month+1)."-".$year);
$endDate->setTime(0, 0, 0);

$notes = $this->em->getRepository('AppBundle:Note')->createQueryBuilder('n')->where('n BETWEEN :start AND :end')->setParameter('start', $startDate->format('Y-m-d H:i:s'))->setParameter('end', $endDate->format('Y-m-d H:i:s'))->getQuery()->getResult();

return $notes;
 }

【问题讨论】:

  • 提供代码以显示您尝试过的内容。

标签: php symfony date select doctrine


【解决方案1】:

将这样的内容放入您的存储库中应该可以帮助您入门。除了似乎可以正常工作的'last day of this month' 位之外,我还没有对其进行测试。

/**
 * @param int $month
 * @param int $year
 * 
 * @return object[]
 */
public function findByDate($year = null, $month = null)
{
    if ($month === null) {
        $month = (int) date('m');
    }

    if ($year === null) {
        $year = (int) date('Y');
    }


    $startDate = new \DateTimeImmutable("$year-$month-01T00:00:00");
    $endDate = $startDate->modify('last day of this month')->setTime(23, 59, 59);

    $qb = $this->createQueryBuilder('object');
    $qb->where('object.date BETWEEN :start AND :end');
    $qb->setParameter('start', $startDate->format('‌​Y-m-d H:i:s'));
    $qb->setParameter('end', $endDate->format('‌​Y-m-d H:i:s'));

    return $qb->getQuery()->getResult();
}

【讨论】:

  • DateTime modify 更改对象并且不会创建新实例,因此 $startDate 和 $endDate 将是相同的。 $endDate = (clone $startDate)->modify('last day of this month') 应该可以工作。或者只是创建第二个实例。
  • 使用代码时出现这些错误执行'SELECT n0_.id AS id0,n0_.slug AS slug1,n0_.content AS content2,n0_.timestamp AS timestamp3,n0_.date AS时发生异常date4, n0_.in_reply_to AS in_reply_to5 FROM note n0_ WHERE n0_.date BETWEEN ?和 ?'带参数 [{"date":"2016-08-01 00:00:00.000000","timezone_type":3,"timezone":"Europe\/London"}, {"date":"2016-08-31 00:00:00.000000","timezone_type":3,"timezone":"Europe\/London"}]:可捕获的致命错误:DateTimeImmutable 类的对象无法转换为字符串
  • 试试$qb->setParameter('start', $startDate->format('Y-m-d H:i:s'));,endDate也一样
  • @Joe 我使用了 DateTimeImmutable ,它不会修改日期对象。我想这也可能是未经修改的教义拒绝接受对象的原因。
  • 哦,是的,对不起,我刚刚停在 DateTime,因为我很少使用不可变的 :) 转换不起作用的原因是操作的下一个答案。他忘记了 where 条件中的.date 部分。与不可变的 DateTime 无关。
【解决方案2】:

这似乎有效,尽管我肯定需要修改构建日期的方式(并将函数移动到 repo 中)。原来我忘记了DQL的'.date'位,也没有必要将DateTime对象输出为格式。

// Create two times at the start of this month and next month
$startDate = \DateTime::createFromFormat('d-n-Y', "01-".$month."-".$year);
$startDate->setTime(0, 0 ,0);

$endDate = \DateTime::createFromFormat('d-n-Y', "01-".($month+1)."-".$year);
$endDate->setTime(0, 0, 0);

$notes = $this->em->getRepository('AppBundle:Note')->createQueryBuilder('n')->where('n.date BETWEEN :start AND :end')->setParameter('start', $startDate)->setParameter('end', $endDate)->getQuery()->getResult();

// $notes = $this->em->getRepository('MrshllSiteBundle:Note')->findByDate();
return $notes;

【讨论】:

    【解决方案3】:

    非常重要的时刻。使用setParameter的数据类型。

    喜欢 symfony。

    使用 Doctrine\DBAL\Types\Type;

    $query->setParameter('start', $startDate, Type::DATETIME);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 2019-05-22
      • 2013-06-08
      相关资源
      最近更新 更多