You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Doctrine按年倒序查询DateTimeImmutable字段当年最新记录

查询指定年份最后一条入库记录的修复方案

原有代码的问题点

  • 核心匹配逻辑错误:createdAt字段存储的是完整日期时间格式(如2023-11-15 14:23:05),直接用d.createdAt = :year和年份数字(如2023)做等值匹配,永远无法命中有效记录,这是返回空数组的主要原因。
  • 存在语法笔误:初始化$year的代码行末尾多了无意义的句点,会触发PHP语法解析错误。
  • 排序逻辑偏差:原代码按传入的业务字段numeroDevis倒序,无法保证取到的是当年最后一条入库的记录,除非该字段是严格随入库时间递增的自增字段。
  • 结果获取方式冗余:查询明确限制只返回1条结果,用getResult()返回数组还需要额外取元素,不符合场景需求。

修复后的实现代码

调用侧代码

$column = "numeroDevis";
// 修正原代码的语法笔误,直接获取当前年份的数字值
$year = (new DateTimeImmutable('now'))->format('Y');
// 调用查询方法
$lastEntry = $this->getRepository(YourEntity::class)->findLastEntryFromThisYear($column, (int)$year);

仓库类查询方法

public function findLastEntryFromThisYear(string $column, int $year): ?object
{
    // 生成目标年份的起止时间范围,用范围查询替代年份函数匹配
    $yearStart = new DateTimeImmutable(sprintf('%d-01-01 00:00:00', $year));
    $yearEnd = $yearStart->modify('+1 year');

    return $this->createQueryBuilder('d')
        ->where('d.createdAt >= :yearStart')
        ->andWhere('d.createdAt < :yearEnd')
        ->andWhere(sprintf('d.%s IS NOT NULL', $column))
        ->setParameter('yearStart', $yearStart)
        ->setParameter('yearEnd', $yearEnd)
        // 按创建时间倒序,确保第一条就是当年最新入库的记录
        ->orderBy('d.createdAt', 'DESC')
        ->setMaxResults(1)
        ->getQuery()
        // 单条查询直接返回实体对象,无匹配时返回null
        ->getOneOrNullResult()
    ;
}

优化说明

  • 采用时间范围匹配替代YEAR(d.createdAt) = :year的函数查询写法,可命中createdAt字段的数据库索引,数据量大时查询性能提升明显。
  • 增加参数类型声明,从语法层面避免传入非法格式的参数。
  • 用getOneOrNullResult()替代getResult(),直接返回单条实体或null,省去后续数组判断的冗余代码。

内容的提问来源于stack exchange,提问作者René Wetta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:24:15