leftJoin('classes', 'classSection.class_id', '=', 'classes.id') ->select('classSection.*', 'classes.class_name'); if (!empty($filters['search'])) { $term = '%' . strtolower((string) $filters['search']) . '%'; $query->where(function ($q) use ($term) { $q->whereRaw('LOWER(classSection.class_section_name) LIKE ?', [$term]) ->orWhereRaw('LOWER(classes.class_name) LIKE ?', [$term]); }); } if (!empty($filters['class_id'])) { $query->where('classSection.class_id', (int) $filters['class_id']); } if (!empty($filters['school_year'])) { $query->where('classSection.school_year', (string) $filters['school_year']); } if (!empty($filters['semester'])) { $query->where('classSection.semester', (string) $filters['semester']); } if (!empty($filters['with_students'])) { $query->whereExists(function ($sub) use ($filters) { $sub->selectRaw('1') ->from('student_class as sc') ->join('students as s', 's.id', '=', 'sc.student_id') ->whereColumn('sc.class_section_id', 'classSection.class_section_id') ->where('s.is_active', 1); if (!empty($filters['school_year'])) { $sub->where('sc.school_year', (string) $filters['school_year']); } }); } $sortBy = (string) ($filters['sort_by'] ?? 'class_section_name'); $sortDir = strtolower((string) ($filters['sort_dir'] ?? 'asc')) === 'desc' ? 'desc' : 'asc'; $allowedSorts = [ 'class_section_name' => 'classSection.class_section_name', 'class_section_id' => 'classSection.class_section_id', 'class_id' => 'classSection.class_id', 'school_year' => 'classSection.school_year', 'semester' => 'classSection.semester', 'class_name' => 'classes.class_name', ]; $sortColumn = $allowedSorts[$sortBy] ?? $allowedSorts['class_section_name']; $query->orderBy($sortColumn, $sortDir); return $query->paginate($perPage, ['*'], 'page', $page); } public function find(int $id): ?ClassSection { return ClassSection::query() ->leftJoin('classes', 'classSection.class_id', '=', 'classes.id') ->select('classSection.*', 'classes.class_name') ->where('classSection.id', $id) ->first(); } }