首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

ThinkPHP5 作業管理系統:高效查詢學生已交與未交作業的實作策略

     編輯:PHP 綜合知識

業務場景與資料關聯

在作業管理系統中,學生登入個人中心需查看「已提交」與「未提交」兩類作業清單。核心涉及三張資料表的關聯關係:

  • Student (學生表):含 stu_no (學號)、stu_id (主鍵)、clas_id (所屬班級)
  • Clas (班級表):含 clas_id、與 Task (作業表) 為多對多關聯
  • Submit (提交表):記錄 stu_id、task_id、提交內容等

邏輯鏈條:學生 → 班級 → 班級所有作業 → 依提交表篩選已/未交。

核心方法實作

1. 取得學生所屬班級的所有作業

// Student 模型中
public function getTasks($stuno)
{
    $student = self::get(['stu_no' => $stuno]);
    if (!$student) return [];
    
    $class = Clas::get(['clas_id' => $student['clas_id']]);
    return $class ? $class->task : []; // 依賴模型關聯定義
}

利用 ThinkPHP 模型關聯 (belongsToMany 或 hasMany),直接透過 $class->task 獲取作業集合,回傳二維陣列。

2. 取得未提交作業 (差集邏輯)

public function getUnSubmitTasks($stuno)
{
    $student = self::get(['stu_no' => $stuno]);
    if (!$student) return [];
    
    $allTasks = $this->getTasks($stuno);
    $stuId = $student['stu_id'];
    
    // 優化:一次查詢該生所有已提交 task_id,避免 N+1 問題
    $submittedIds = Submit::where('stu_id', $stuId)
        ->column('task_id'); // 返回一維陣列 [task_id1, task_id2, ...]
    
    // 過濾:保留不在已提交清單中的作業
    return array_filter($allTasks, function ($task) use ($submittedIds) {
        return !in_array($task['task_id'], $submittedIds);
    });
}

效能優化說明:原範例在迴圈中逐筆查詢 Submit::get() 會造成 N+1 查詢問題。改用 column() 一次撈取所有已提交 ID,再用 array_filter 過濾,資料庫查詢從 N+1 降為 2 次。

3. 取得已提交作業 (補集邏輯)

public function getSubmitTasks($stuno)
{
    $allTasks = $this->getTasks($stuno);
    $unsubmitted = $this->getUnSubmitTasks($stuno);
    
    // 建立未提交 task_id 查找表 (O(1) 查找)
    $unsubmittedIds = array_column($unsubmitted, 'task_id');
    
    return array_filter($allTasks, function ($task) use ($unsubmittedIds) {
        return !in_array($task['task_id'], $unsubmittedIds);
    });
}

同樣採用 array_column + in_array 替代雙重迴圈,時間複雜度從 O(n²) 降為 O(n)。

進階優化建議

  1. 單一查詢完成分組:使用 SQL LEFT JOIN + CASE WHEN 或 IF,一次查詢即可標記每筆作業的提交狀態,完全避免 PHP 端陣列運算。
  2. 快取機制:班級作業清單變動較少,可快取 getTasks 結果,降低資料庫負載。
  3. 分頁處理:作業數量大時,前端需分頁,後端應支援 limit/offset 或游標分頁,避免一次載入過多資料。
  4. 模型關聯預載入:Clas::with('task')->get(...) 減少查詢次數。
  5. 總結

    本文展示了從基礎邏輯到效能優化的完整演進。核心原則:善用資料庫集合運算替代應用層迴圈查詢、利用陣列索引加速查找。ThinkPHP5 的模型關聯與查詢構建器提供了優雅的語法支撐,開發者只需關注業務邏輯與 SQL 效能即可構建高效的作業管理查詢功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved