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

bhamra's avatar

Getting records from row wise to column wise in json format laravel

I want to get result like this in json format student id wise.

data:
0:
Exam_Name : "first term"
marks : "English : 75, Math : 80, Science : 70"
1:
Exam_Name : "second term"
marks : "English : 72, Math : 82, Science : 86"

There are two tables Exam & exam results

Exam has id, name, class_id columns
id         name           class_id
1       first term             1
2       second term            1

Exam_Results has exam_id, student_id  subject, marks columns
id       exam_id     student_id        subject      marks
1         1            1                english       75
2         1            1                 math         80
3         1            1                science       70
4         2            1                english       72
5         2            1                 math         82
6         2            1                science       86

Here is my controller file

$results =ExamResults::join('exam','exam_results.exam_id', '=', 'exam.id')
        ->select('exam.name','exam_results.*')
        ->where('student_id',$student->id)->get();

$data   = [];

foreach($results as $row){
    $data[] = [
        'exam_name'          =>$row->name,
        'marks'         =>$row->subject." : ".$row->marks,
        ];
}
return response()->json(['data' => $data,]);

with this i m getting result like below

data:
0:
exam_name: "first term"
marks: "english : "75"
1:
exam_name: "first term"
marks: "math : "80"
2:
exam_name: "first term"
marks: "science : "70"
3:
exam_name: "second term"
marks: "english : "72"
4:
exam_name: "second term"
marks: "math : "82"
5:
exam_name: "second term"
marks: "science : "86"

Please help

0 likes
11 replies
Tray2's avatar

It's always a bit tricky with nested relations.

You need to do something like

SELECT  e.name, 
(SELECT er.marks FROM exam_results er WHERE er.exam_id = e.id AND subject = 'english') marks_english,
(SELECT er.marks FROM exam_results er WHERE er.exam_id = e.id AND subject = 'math') marks_math,
FROM exams e;
bhamra's avatar

but subject can vary from student to student

DiogoGomes's avatar

You should set a relation on your models and use Eloquent.

Example would be:

class Exam extends Model
{
    public function results()
    {
        return $this->hasMany(ExamResult::class);
    }
}

Then you could do something like this:

    return App\Models\Exam::with('results')->get()->map(function(App\Models\Exam $exam){
        return [
            'Exam_Name' => $exam->name,
            'marks' => $exam->results->pluck('marks', 'subject')
        ];
    })->toJson();
bhamra's avatar

There are students also involved. i am trying to get it student id wise.

but this way it throws all the exam ,results and random marks

Tray2's avatar

So you have the student

$student = Student::findOrFail($id);

With that student you can get all it's marks

$studentMarks = Marks::where('student_id', $student->id)->get();

Now since you want it for a certain term you add another where clause.

$studentMarks = Marks::where('student_id', $student->id)->where('term_id', $term->id)->get();

If you have set up the correct relationhips you cand do something like this

$student = Student::findOrFail($id)->with('marks');
bhamra's avatar

if u see my result it is student wise this is the result of the one student.

The problem is it is expanded subject wise but i want to combine all subjects under exam name.

bhamra's avatar

I have made some changes to controller file and got the result

data:
0:
Exam_Name : "first term"
marks : ["English","Math","Science"]  : ["75","80","70"]
1:
Exam_Name : "second term"
marks : ["English","Math","Science"]  : ["72","82","86"]

But i want it like

data:
0:
Exam_Name : "first term"
marks : "English : 75, Math : 80, Science : 70"
1:
Exam_Name : "second term"
marks : "English : 72, Math : 82, Science : 86"

Here is controller file

public function exam($id)
	{
		$student = Student::find($id);		
		$exams = ExamResults::where('student_id',$id)->select('exam_id')
                 ->orderBy('exam_id','DESC')
                ->distinct() - >pluck('exam_id')->toArray();
		
$data   = [];			
		foreach($exams as $exam)
		{
                 $exm = Exam::where('id',$exam)->first();

		 $subject = ExamResults::where('exam_id',$exm->id)
                  ->where('student_id',$student->id)->pluck('subject');

		 $mark = ExamResults::where('exam_id',$exm->id)
                 ->where('student_id',$student->id) ->pluck('marks');
		 
		$data[] = [			
			'exam_name' 	=> $exm->name,
			'marks'         => $subject." : ".$mark
				
			];
		
		}
		
return response()->json(['data' => $data]);
	}
DiogoGomes's avatar

You can do it with a single query, groupBy and map:

    return DB::table('exam_results')
        ->join('exams', 'exams.id', 'exam_results.exam_id')
        ->where('exam_results.student_id', $student_id)
        ->get()
        ->groupBy('exam_id')
        ->map(function(\Illuminate\Support\Collection $exams) {
            return [
                'Exam_Name' => $exams->first()->name,
                'marks' => $exams->pluck('marks','subject')
            ];
        })->values();

This will return:

[
  {
    "Exam_Name": "first term",
    "marks": {
      "english": 75,
      "math": 80,
      "science": 70
    }
  },
  {
    "Exam_Name": "second term",
    "marks": {
      "english": 72,
      "math": 82,
      "science": 86
    }
  }
]
bhamra's avatar

by this i am getting. subject names are not showing and getting only the last marks in the table

	
0	
Exam_Name	"first term"
marks	
	             :   	"70"
1	
Exam_Name	"second term"
marks	
                     :   	"86"

DiogoGomes's avatar

the solution that I've sent you should work.

Is your column name marks or mark?

Please or to participate in this conversation.