Skip to content

波林部落客

PolinWEI Blog

  • Web Server
  • PHP
  • WordPress
  • Laravel
  • VueJS
  • NodeJS
  • Ubuntu
  • 網路技術
  • Toggle search form
  • powershell 指令刪除已掛載的網路磁碟機 網路技術
  • image 17
    Laravel 自動記錄資料建立者/更新者/刪除者 – 波林部落客 Laravel
  • SQL Server 日期查詢範例 網路技術
  • image 8
    Laravel for Visual studio code 的開發環境設置 Laravel
  • image 16
    Vue3 與 Laravel 前後端 Timezone 轉換傳值解決方式 VueJS
  • WordPress 佈景 style.css WordPress
  • mmc add ad schema 768x531 1
    Active Directory 操作主機角色移轉與拿取 網路技術
  • image 17
    使用 Cloudflare 的SSL憑證並整合CDN WordPress
image

Laravel 模型中使正確取得兩個日期之間資料的方法

Posted on 2025-06-042025-06-04 By polinwei 在〈Laravel 模型中使正確取得兩個日期之間資料的方法〉中尚無留言

假設有一個部落格,想檢索兩個日期之間的所有貼文。聽起來很熟悉?那具體該怎麼做呢?

image

Table of Contents

Toggle
  • 一般的做法
  • 較好的 Carbon 利用方法
  • 另一種方法: Filter
  • Eloquent 其它種方法
  • 參考:

一般的做法

這看起來確實是一個微不足道的問題,答案也很簡單(但完全錯誤):只需使用 BETWEEN(或在 Laravel 中使用 whereBetween),如下所示:

$startDate = '2025-06-01';
$endDate = '2025-06-30';

$posts = Post::whereBetween( $published_at, [$startDate, $endDate])->get();

大部份的人都這樣做過(至少我這樣做過),檢索 6 月發布的所有帖子。這裡的問題是,published_at 列通常是 Datetime 類型,所以它不僅僅是一個簡單的日期,還包含一個時間。這意味著實際上 2025-06-30 日發布的文章不會被檢索到,因為它們的發布日期總是大於 2025-06-30(SQL 會將其理解為“2025-06-30 00:00:00”)。

$startDate = Carbon::createFromFormat('Y-m-d', '2025-06-01');
$endDate = Carbon::createFromFormat('Y-m-d', '2025-06-30');

$posts = Post::whereBetween('published_at', [$startDate, $endDate])->get();

這實際上更糟糕,因為它變得完全不可預測。 Carbon 實例代表一個時刻,它也有一個時間,除非不指定時間,否則它會預設為運行時的當前時間。所以,如果在上午 9 點運行時,而文章是在 30 號上午 8 點發布的,你就能檢索到它……但是,如果是在上午 7 點運行完全相同的腳本,將無法再檢索到該文章,因為 $endDate 實際上是“2025-06-30 07:00:00”。

我們可以使用 $endDate->toDateString() 來去除時間,但最終還是會回到上面的情況。

較好的 Carbon 利用方法

一種解決方案是確保在查詢中指定一個時間,並且該時間對於開始日期來說是一天的開始時間(00:00:00),對於結束日期來說是一天的結束時間(23:59:59.999999)。

幸運的是,Carbon 提供了 startOfDay() 和 endOfDay() 方法來實現這一點:

$startDate = Carbon::createFromFormat('Y-m-d', '2025-06-01')->startOfDay();
$endDate = Carbon::createFromFormat('Y-m-d', '2025-06-30')->endOfDay();

$posts = Post::whereBetween('published_at', [$startDate, $endDate])->get();

另一種方法: Filter

Laravel 提供很多方法(Available Methods),也可以先將資料以 where 條件篩選出來,透過 get() 取得資料後,再使用 filter() 作細部篩選。

$data = BlogPost::where([
	['status', '=', 'published'],
	['visible', '=', 'public']
])->get()
	->filter(function ($item) {
		if (isset($item->published_at) && isset($item->unpublished_at)) {
			if ( Carbon::now()->between($item->published_at, $item->unpublished_at) ) {
				return $item;
			}
		} else if (isset($item->published_at) && !isset($item->unpublished_at)) {
			if ( Carbon::now() > $item->published_at ) {
				return $item;
			}
		} else {
			return;
		}
	});

在程式中,使用 Carbon::now() 取得當時的時間,再與 published_at & unpublished_at 作比較,這也可以得到發佈與下架日期之間的文章。

Eloquent 其它種方法

Eloquent 提供了一個非常有用的 whereDate() 方法,它可以做兩件事:

  • 建立 SQL 查詢,使用 DATE() 的 SQL 函數將列內容格式化為 Y-m-d 格式。
  • 在比較 Carbon 或 Datetime 物件之前,將其正確地轉換為 Y-m-d 格式。

使用這個方法,我們可以放心地傳遞 Carbon 實例,並且知道其中包含的任何時間都會被丟棄,我們實際上是在兩個日期之間進行搜尋:

$startDate = Carbon::createFromFormat('Y-m-d', '2025-06-01');
$endDate = Carbon::createFromFormat('Y-m-d', '2025-06-30');

$posts = Post::query()
    ->whereDate('published_at', '>=', $startDate)
    ->whereDate('published_at', '<=', $endDate)
    ->get();

這將產生以下 SQL 查詢:

SELECT * from "posts"
WHERE DATE("published_at") >= '2025-06-01'
AND DATE("published_at") <= '2025-06-30';

參考:

How to properly retrieve Laravel models between two dates

Laravel Tags:Eloquent

文章導覽

Previous Post: Laravel 中的同步(Sync)、附加(Attach)和分離(Detach):使用 Eloquent 管理關係
Next Post: 在 Vue.js 建立一個 公用方法 來 移除 HTML 標籤

Related Posts

  • Laravel 10 信箱認證(Email Verification) Laravel
  • Laravel 在 middleware 裡如何取得目前登入帳號的資訊 Laravel
  • image 17
    Laravel 自動記錄資料建立者/更新者/刪除者 – 波林部落客 Laravel
  • laravel welcome
    Laravel 10 快速建立認證系統 Laravel
  • image 21
    Laravel 中的同步(Sync)、附加(Attach)和分離(Detach):使用 Eloquent 管理關係 Laravel
  • 在 Ubuntu Server 安裝 Apache + MariaDB + PHP Laravel

發佈留言 取消回覆

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


apache blade database debug DNS Eloquent fortigate linux middleware nginx permission powershell queue redis Springboot SQL Server timezone trait Visual Studio Code vue3 windows zabbix 佈景主題

  • laravel log file
    Laravel Log 設定與使用 Laravel
  • image 3
    FortiGate 用 ip port-forward(埠號轉發) 設定 FTP 網路技術
  • 在 Ubuntu Server 安裝 Apache + MariaDB + PHP Laravel
  • image 36
    Jenkins 自動部署 Spring Boot 並自動起動 Java
  • laravel welcome
    Laravel 10 快速建立認證系統 Laravel
  • powershell 指令刪除已掛載的網路磁碟機 網路技術
  • image 21
    Laravel 中的同步(Sync)、附加(Attach)和分離(Detach):使用 Eloquent 管理關係 Laravel
  • image 3
    Vue Skeleton 載入畫面與 Suspense 元件的應用 VueJS

Copyright © 2025 波林部落客.

Powered by PressBook News WordPress theme