Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

shariff's avatar
Level 50

Laravel groupBy query (API Resource)

Hi

I am trying to get a student marks details that are group by exam_type. I need to create a API in below format. But I am unable to do that one. I need help with building query.

{

  "success": true,
  "data": [

      {
        "exam_type": "Annually",
         "details":[
                       {

              // all student marks details  group by exam_type

                  "student_id": 89,
                 "subject": "English",
                 "marks": "50",
                 "marksgrade": "B",
                 "total": "300",
                   "grade": "B",
                  "percentage": "50",
                  "year": "2019"
              },
             {

              // all student marks details  group by exam_type

                  "student_id": 89,
                 "subject": "Mathematics",
                 "marks": "50",
                 "marksgrade": "B",
                 "total": "300",
                   "grade": "B",
                  "percentage": "50",
                  "year": "2019"
              },

           ],

      }
]

}

what I have tried

$marks = StudentMarksResource::collection(StudentsMark::whereIn('academic_id',$ids)
->whereIn('student_id',$studentid)->get()->groupBy('exam_type')); 

Resource file

  public function toArray($request)
   {
       
       return [
           
           'exam_type' => $this->exam_type,
           'class_id' => Course::find($this->class_id),
           'batch_id' => Batch::find($this->batch_id),
           'student_id' => Student::find($this->student_id),
           'subject' => $this->subject,
           'marks' => $this->marks,
           'marksgrade' => $this->marksgrade,
           'total' => $this->total,
           'grade' => $this->grade,
           'percentage' => $this->percentage,
           'year' => $this->year,
           
       ];
   }


how i am sending the data


return response()->json(['success' => true,'data' =>  $marks,'status' => 200]);

0 likes
17 replies
shariff's avatar
Level 50

@sinnbeck No that is for time table. that is working fine. This is for student marks, In this I am not getting the data in the above format

Sinnbeck's avatar

But you are again trying to groupBy on the data before sending in into the resource. That is the same issue as before

$marks = StudentMarksResource::collection(StudentsMark::whereIn('academic_id',$ids)
->whereIn('student_id',$studentid)->get()->groupBy('exam_type'));
shariff's avatar
Level 50

@sinnbeck I have tried this also. how you have told me yesterday

     ```    $marks = DB::table('students_marks')
         ->whereIn('academic_id',$ids)
         ->whereIn('student_id',$studentid)
         ->get()->groupBy('exam_type')->map(function($group){
             return StudentMarksResource::collection($group);
         });```
Sinnbeck's avatar

I have been thinking but I dont see any clever way of doing this, as it kinda breaks how an api resource works.

This is untested buy try something like this and see what you get

 public function toArray($request)
   {
       foreach ($this as $item) {
            $data[]['details'] =  [
           
           'exam_type' => $titemis->exam_type,
           'class_id' => Course::find($item->class_id),
           'batch_id' => Batch::find($item->batch_id),
           'student_id' => Student::find($item->student_id),
           'subject' => $item->subject,
           'marks' => $item->marks,
           'marksgrade' => $item->marksgrade,
           'total' => $item->total,
           'grade' => $item->grade,
           'percentage' => $item->percentage,
           'year' => $item->year,
           
       ];
       }
       return $data;
   }
bugsysha's avatar
$marks = DB::table('students_marks')
         ->whereIn('academic_id',$ids)
         ->whereIn('student_id',$studentid)
         ->get()
    ->map(
        // here you return new StudentResource($student) or what ever you named resource and model/variable
    )
    ->groupBy(
        // then you group by the desired prop, not sure does your resource collection has any specific data on it
    );
bugsysha's avatar

Or also you can return without grouping and then just group it on the front end. You should return your resources to be as plain as possible so you can reuse them. If the presentation layer of your app requires grouping then group it there.

bugsysha's avatar

@matheenulla sure thing. Point is that by grouping something you will probably need that only in one place. But without grouping you can use it at multiple places. Like having orders. If you want to group them per day then probably that is just one place in the app, while showing them one by one which you normally do in your index controller method will be usable in many shapes and forms. Like many programmers tend to group things while they need filtering.

Hope it makes sense.

shariff's avatar
Level 50

@bugsysha @sinnbeck I have one small doubt. I am totally new to this API and I don't know how they will build mobile apps using API. My Doubt is, we need to create API how a mobile app developer will say? or we just need to give API and rest of the things they will do? .

bugsysha's avatar

There is almost always some kind of transformation which you do on the device which receives response from API so do not worry about it. But if you have unreasonable people around you then there is nothing you can do but to group them.

If that is the case then I think my first reply should work.

shariff's avatar
Level 50

@bugsysha I tried that one I am getting an error Call to undefined method stdClass::first()

$marks = DB::table('students_marks')
        ->whereIn('academic_id',$ids)
        ->whereIn('student_id',$studentid)
        ->get()
        ->map(function($group){
            StudentMarksResource::collection($group);

          })
        ->groupBy('exam_type');
bugsysha's avatar

Maybe cause you haven't returned anything from your map().

return StudentMarksResource::collection($group);

And are you sure that you get something that you should name $group as a parameter in a callback in map? It should be single stdObject instance of $studentMark.

1 like
shariff's avatar
Level 50

@sinnbeck @bugsysha finally the exact output what I want that I am getting now. Thank you very very very much for helping me. I was suffering this from last 2 days thank you once again

shariff's avatar
shariff
OP
Best Answer
Level 50

@sinnbeck @bugsysha I have made changes like this

 $exam_types = StudentsMark::whereIn('academic_id',$ids)->whereIn('student_id',$studentid)->distinct()->get(['exam_type','academic_id','student_id']);

       $marks = StudentMarksResource::collection($exam_types);

resource file is

public function toArray($request)

{    
    return [

        'exam_type' => $this->exam_type,
        'details' => StudentMarks::where('academic_id', $this->academic_id)
        ->where('student_id', $this->student_id)
        ->where('exam_type',$this->exam_type)
        ->get(),

    ];
}

thank you once again

bugsysha's avatar

You are very welcome. Glad you solved it. Now go and listen to some Jimi Hendrix to relax 🙂

1 like

Please or to participate in this conversation.