iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
Modern Web

後端菜雞仔想學 Laravel系列 第 20

orWhere、orderBy:關鍵字搜尋邏輯更新、加入排序機制!

  • 分享至 

  • xImage
  •  

昨天設定完關鍵字搜尋後,覺得我這部份的需求沒有定義得很明確!
導致 index 的程式碼沒有很接近我的需求想像。

雖然這次的挑戰是前後端分離,沒有帶入前端,但根據昨天的關鍵字搜尋設定,可以想像出前端可能需要兩個關鍵字輸入方框,並且也沒有辦法查詢所有產品,這樣也並不符合我想要的使用者體驗。

今天再重新梳理關鍵字搜尋的需求並進行修正,然後一併加入排序機制!GO~

關鍵字搜尋 + 排序機制

情境想像

  • 線上產品瀏覽系統裡除了甜點,還會有茶品類,品項可能會有好幾種,產品敘述也各不相同,可以再自己設定其他類別的產品。

  • 在線上菜單系統裡只有「一個」輸入方框,能在這個方框裡輸入關鍵字進行搜尋。

  • 因為每個人的直觀想法不同,如果對於關鍵字沒有定義,會增加搜尋困難度,但如果拆解成每一個字進行搜尋,可能也無法精準搜尋產品,降低使用者體驗。
    所以我會將前端的輸入方框定義為:品名搜尋
    讓使用者直觀想到:「這個搜尋方框是用來搜尋品名的」,引導使用者輸入與品名相關的關鍵字。
    例如:紅茶、杏仁瓦片等等。

  • 假設我希望能搜尋所有紅茶讓我挑選,所以我會在方框裡直觀的輸入:「紅茶」,按下按鈕進行搜尋後,則需要將與「紅茶」所有相關產品都列出!並且列表第一個需顯示最新上架的產品。

  • 如果方框內沒有值,則列出所有產品。

範例需求

限制方框裡僅能輸入 10 個字以內,並只接受繁體中文,不接受其他語言。

篩選相關產品定義

  • 假設關鍵字搜尋為「紅茶」,則「產品名稱」及「產品敘述」如果有「紅茶」都會一起被篩選出來!

排序機制定義

  • 將關鍵字所有相關產品篩選出後,須依照「最新上架到最舊上架」排序列出!

分頁定義

  • 每頁僅列出 10 筆資料。

關鍵字搜尋邏輯

  1. 驗證輸入的關鍵字是否符合規則,如果驗證失敗則回傳錯誤訊息,並請使用者重新輸入。
  2. 取得輸入的關鍵字。
  3. 如果有關鍵字,執行關鍵字搜尋,否則列出所有產品。
  4. 篩選出所有符合相關產品定義的產品,並確認僅在「產品名稱」、「產品敘述」的欄位進行關鍵字搜尋。
  5. 將「created_at」的欄位當作「最新上架」的判斷依據。
  6. 在查詢中使用 orderBy() 方法指定排序條件,並接著用 paginate() 來設定分頁功能。

修改ProductController.php

public function index(Request $request)
{
    // 驗證輸入的關鍵字是否符合規則:限制輸入 10 個字以內,並只接受繁體中文
    $validator = Validator::make($request->all(), [
        'keyword' => 'nullable|string|max:10|regex:/^[\p{Han}]+$/u',
        ]);
    // 如果驗證失敗,回傳錯誤訊息
    if ($validator->fails()) {
        return response()->json([
            'message' => '請重新輸入!',
            'errors' => $validator->errors(),
        ], Response::HTTP_BAD_REQUEST); // 回傳 HTTP 400 錯誤
    }
    // 取得查詢關鍵字
    $keyword = $request->input('keyword');

    // 如果有關鍵字,執行關鍵字搜尋,否則列出所有產品
    if ($keyword) {
        $products = Product::where('product_name', 'LIKE', "%$keyword%")
                            ->orWhere('product_description', 'LIKE', "%$keyword%")
                            ->orderBy('created_at', 'desc') // 按照最新上架的產品排序
                            ->paginate(10); // 固定每頁 10 筆資料
    } else {
        // 沒有關鍵字時列出所有產品
        $products = Product::orderBy('created_at', 'desc') // 按照最新上架的產品排序
                            ->paginate(10); // 固定每頁 10 筆資料
    }
    // 回傳產品列表
    return response()->json($products);
}


orWhere 的概念

主要是將多個查詢條件結合在一起。
當你想要添加一個「或」的條件時,就可以使用 orWhere。
如果第一個條件不成立,則檢查第二個條件。

基本用法

上述範例:

$products = Product::where('product_name', 'LIKE', "%$keyword%")
                    ->orWhere('product_description', 'LIKE', "%$keyword%")
                    ->orderBy('created_at', 'desc') // 按照最新上架的產品排序
                    ->paginate(10); // 固定每頁 10 筆資料

Product::where()

這是查詢的起點,我們使用 where 來設定第一個條件:產品名稱包含特定的關鍵字。

'product_name', 'LIKE', "%$keyword%"

表示我們要查詢 product_name 字段中包含關鍵字的產品。
LIKE 用於模糊查詢,% 表示任意數量的字符。

orWhere()

將另一個條件加進來,如果第一個條件不滿足,則檢查第二個條件:產品描述是否包含相同的關鍵字。

orderBy 的概念:

主要是對查詢結果進行排序:可以根據指定的欄位對資料進行升序或降序排列。
無論是單一欄位還是多個欄位的排序都可以。

單一排序

$query->orderBy('column', 'direction');

column:你想要排序的欄位名稱。例如:created_at、price 等。
direction:排序的方向,可以是 'asc'(升序)或 'desc'(降序)。
升序是從小到大,降序則是從大到小。

多重排序

對多個欄位進行排序。

範例:

假設我們希望先依 type_id 進行「升序」排序,再依 price 進行「降序」排序:

$products = Product::orderBy('type_id', 'asc')
                    ->orderBy('price', 'desc')
                    ->get();

更多相關資訊可以參考官方文件:


使用 Postman 測試

  • 假設輸入方框的內容為:紅茶

https://ithelp.ithome.com.tw/upload/images/20241004/20169300n8AO1I44fj.jpg

顯示「產品名稱」及「產品敘述」包含「紅茶」關鍵字的所有產品,並以最新上架日期進行排序。即為測試成功!

  • 假設輸入超過 10 個字

https://ithelp.ithome.com.tw/upload/images/20241004/20169300LOMsXLlBTR.jpg

顯示設定好的錯誤訊息,即為測試成功!

  • 假設輸入方框裡沒有值

https://ithelp.ithome.com.tw/upload/images/20241004/20169300A1oKwYI2TA.jpg

顯示所有產品,並以最新上架日期進行排序,即為測試成功!


上一篇
關鍵字搜尋:建立一個簡單的篩選查詢器吧!
下一篇
分類 CRUD:指派另一位店長!
系列文
後端菜雞仔想學 Laravel30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言