Laravel eloquent relationship 4 table problem - laravel

my db table is
===batches ===
id
batch_title
===courses===
id
course_title
batch_id
===students ===
id
name
===course_student===
course_id
student_id
now i want to show how many students are join in this batch and also how many students in this course
my Student model
public function courses()
{
return $this->belongsToMany('App\Course');
}
Course Model
public function students(){
return $this->hasManyThrough('App\Course','App\Student');
}
public function batch() {
return $this->belongsTo('App\Batch','batch_id');
}
Batch Model
public function courses(){
return $this->hasOne('App\Course','batch_id');
}

You have many weakness in your code:
first to should rebuild your many to many relation between Course and Student according to many to many doc
Student Model
public function courses()
{
return $this->belongsToMany(Course::class);
}
Course Model
public function students()
{
return $this->belongsToMany(Student::class);
}
now: to get how many Student in this course:
$value = Course->withCount('students')->find($courseId);
$studentsCount = $value->students_count;
$students_count will have the student count for Course with id = $couserId
if you want to get Student Count for specific Batch will may walk in the same way:
$coursesInBatch = Course->withCount('students')->where('batch_id',$batchId)->get();
now $coursesInBatch holds the courses for this batch including there students_count
$studentCountInBatch = 0;
foreach ($coursesInBatch as $course) {
$studentCountInBatch += $course->students_count;
}
now $studentCountInBatch will hold how many student in Batch with id($batchId)

Related

Eloquent: Find all records of a table base on a one to many relationship

I have two tables grades and students, each grade belongs to a student. and I want to find all grades based on some students(not a student) that have a common attribute, for example, Students that are a boy.
class Student extends Model
{
public function grades()
{
return $this->hasMany('App\Grade');
}
}
and
class Grade extends Model
{
public function student()
{
return $this->belongsTo('App\Student');
}
}
So, I try this code, but it's wrong because it works if we have a student, not some students:
$grades = Student::where('sex','male')->grades->latest('created_at')->paginate(20);
And I'm looking for the solution!
Yes, the relationship method can be called by one eloquent.
So you just want to get the grades' records of male students, you can just get them out from Grade.
$grades = Grade::whereHas('student', function($q) {
return $q->where('sex', 'male');
})->latest('created_at')->paginate(20);
try this
public function grades()
{
return $this->hasMany('App\Grade','student_id','student_id');
}
$grades = Student::with('grades')->where('sex','male')->latest('created_at')->paginate(20);

Laravel - Get additional attributes of Many to Many table

I got the following tables
actors
id
name
stats
id
name
actor_stat
actor_id
stat_id
quantity
I want, given an actor's name, take all the quantities associated.
Actor model:
class Actor extends Model
{
public function stats()
{
return $this->belongsToMany('App\Stat', 'actor_stat')->withPivot('quantity');
}
}
Stat model:
class Stat extends Model
{
public function users()
{
return $this->belongsToMany('App\User', 'actor_stat')->withPivot('quantity');
}
}
Query
public function request(){
$actors = Actor::where('name','Jack')->first();
$stat = $actors->pivot->quantity; //??
return response()->json(['actors' => $actors, 'stat' => $stat]);
}
Suggestions?
you can use eager loading to load related table like this:
$actors = Actor::with('stats')->where('name','Jack')->first();
//do loop foreach actor state then you can access to quantity column
foreach($actors->states as $state)
$state->pivot->quantity;

Laravel: Sorting Polymophic Relations

HOW TO
In the Student Controller, how to sort the results by student name?
How to sort the results by student's guardian name?
TABLE STRUCTURE
taxonomies
id
entity_type - It contains the class name of the owning model.
entity_id - It contains the ID value of the student.
students
id
name
guardians
id
student_id
name
CONTROLLER
StudentController.php
public function getStudents()
{
return Taxonomy::with([
'entity',
'entity.guardian'
])
->where('entity_type', 'Student')
->get();
}
MODEL
Taxonomy.php
public function entity()
{
return $this->morphTo();
}
Student.php
public function taxonomies()
{
return $this->morphMany('App\Taxonomy', 'entity');
}
public function guardian()
{
return $this->hasOne('App\Guardian');
}
Guardian.php
public function student()
{
return $this->belongsTo('App\Student');
}
Use sortBy():
$taxonomies = Taxonomy::with('entity.guardian')
->where('entity_type', 'Student')
->get();
// Solution #1: Sort results by student name.
$sortedTaxonomies = $taxonomies->sortBy('entity.name');
return $sortedTaxonomies->values();
// Solution #2: Sort results by student's guardian name.
$sortedTaxonomies = $taxonomies->sortBy('entity.guardian.name');
return $sortedTaxonomies->values();

Using eloquent to query multiple tables

I am using Laravel 5.6. I am trying to query information from the grading_info table but I also want to return the students name and other info from the student_info table. I only want to return records in the grading_info table that are related to the currently logged in teacher. Currently its returning information for all teachers. I know I can add a where clause but I am trying to learn eloquent and was wondering if there was any way to accomplish this?
Teachers and students can have many enteries in the grading_info table and any teacher can grade any student.
I would like to return something like this
{
gradeID,
gradeDate,
gradeInfo
.....
student: {
studentName,
studentPhoneNumber,
studentEmail
......
}
}
users table (only stores teachers, not student)
id
teacher_info
teacherID (linked to id from users table)
student_info
id (auto increment. not relation to the users table)
grading_info
studentID (linked to id from student_info)
teacherID (linked to id from users)
User model
public function grades(){
return $this->hasMany(GradingInfo::class, 'studentID');
}
GradingInfo model
public function teacher(){
return $this->belongsTo(User::class, 'id', 'teacherID');
}
public function student() {
return $this->belongsTo(StudentInfo::class, 'studentID', 'id');
}
StudentInfo model
public function grades() {
return $this->hasMany(SessionInfo::class, 'studentID', 'id');
}
TeacherInfo model
// Nothing in here.
TeacherController
public function getGrades(Request $request)
{
$user = Auth::user(); // This is the teacher
$grades = $user->with('sessions.student')->orderBy('created_at', 'DESC')->get();
return response()->json(['sessions' => $sessions], 200);
}
You have Many to Many relationship between user(teacher) and student(student_info) tables
User Model
public function gradeStudents(){
return $this->belongsToMany(StudentInfo::class, 'grading_info', 'teacherID', 'studentID');
}
public function info(){ //get teacher info
return $this->hasOne(TeacherInfo::class, 'teacherID');
}
StudentInfo model
public function gradeTeachers(){
return $this->belongsToMany(User::class, 'grading_info', 'studentID', 'teacherID');
}
Now Fetch the data (TeacherController)
public function getGrades(Request $request)
{
$user = Auth::user(); // This is the teacher
$students = $user->gradeStudents; // it will return all graded students by logged in teacher
return response()->json(['students' => $students], 200);
}
Here grading_info is a pivot table for Many-To-Many relationship
for details check this https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
Fetch Extra info from pivot table
If you want to add extra info in pivot table (grading_info) then add column (info) in this table and then need to change relationship like this
public function gradeStudents(){
return $this->belongsToMany(StudentInfo::class, 'grading_info', 'teacherID', 'studentID')
->withPivot('info')
->as('grade')
->withTimestamps();
}
Now if you fetch data
$user = Auth::user(); // This is the teacher
$students = $user->gradeStudents;
foreach($students as $student){
print_r($student);
print_r($student->grade->info);
print_r($student->grade->created_at);
}

BelongsToMany with one or vice versa relationship

I'm using Laravel and Eloquent.
I have a courses table and a Pivot table that holds the related courses.
My pivot table named relatedCourses has 2 columns, course1 & course2.
In the above example, Course ID 5 is related with Course ID 7.
$data["course"] = course::where("isActive",1)->with('related')->find(5);
This works and brings ID 7 as related.
If i try
$data["course"] = course::where("isActive",1)->with('related')->find(7) it should bring ID 5 as related, this is what i'm trying to achieve.
My code is like this in the model :
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function related()
{
return $this->belongsToMany('App\Models\course', 'relatedCourses', 'course1', 'course2');
}
}
You can define two relationships for this query.
class course extends Model
{
public function category()
{
return $this->hasOne('App\courseCategory',"categoryId");
}
public function relatedCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course1', 'course2');
}
public function originalCourses()
{
return $this->belongsToMany('App\Models\Course', 'relatedCourses', 'course2', 'course1');
}
}
Then you can query your relations,
$data["course"] = course::where("isActive",1)->with('relatedCourses')->find(5);
and
$data["course"] = course::where("isActive",1)->with('originalCourses')->find(7);
To merge both relations you can do like this
$course = course::where("isActive",1)->with('originalCourses', 'relatedCourses')->get();
Hope this will help you.

Resources