Triple Pivot Challenge - php

I have the following challenge, trying to join 3 tables in Laravel 5:
I have a many-to-many relation between 3 table: students, classrooms, terms. I would love to make a call like term->classroom->students.
I saw the Eloquent-triple-pivot package, but unfortunately, I cant get it working for Laravel 5.
Please, I would appreciate solution to bind this and make the call, eloquent or otherwise.
Thank you.
EDIT:
I have many-to-many relationship between 3 tables; classrooms, students, terms.
I have 3 pivot tables: classroom_term, classroom_student, student_term.
And 3 corresponding models: ClassroomTerm, ClassroomStudent, StudentTerm.
My Classroom model:
public function students()
{
return $this->belongsToMany('App\Student')->withTimestamps();
}
public function terms()
{
return $this->belongsToMany('App\Term')->withTimestamps();
}
My Term Model:
public function classrooms()
{
return $this->belongsToMany('App\Classroom')->withTimestamps();
}
public function students()
{
return $this->belongsToMany('App\Student')->withTimestamps();
}
My Student model:
public function terms()
{
return $this->belongsToMany('App\Term')->withTimestamps();
}
public function classrooms()
{
return $this->belongsToMany('App\Classroom')->withTimestamps();
}
What I am doing in my StudentsController is
$term = Term::findOrFail($id);
foreach($term->classrooms as $classroom) {
$studentids = ClassroomStudent::where('classroom_id', '=', $classroom->id)->get();
}
//to get the real student collection
foreach($studentids->student_id as $studentid){
$students = Student::findOrFail($studentid)
}
return view('students.list')->with(['students' => $students]);
In my students.list view, I would simply want to retrieve students:
#foreach($students as $student)
First Name: {{!!$student->first_name!!}}
#endforeach
The error is in this line:
foreach($studentids->student_id as $studentid){
$students = Student::findOrFail($studentid)
}
Undefined property: Illuminate\Database\Eloquent\Collection::$student_id'
However dd($studentids) returned an array and one of the attributes is student_id.
The code is cumbersome and not working.
Thanks for your help
The Goal:
To retrieve the students in the classroom in the term. With many-to-many relationship between classrooms, students and terms.

I think you could be setting the relations not well. Try thinking it well, for example, I think that probably a Student belongsTo a Classroom.
Classroom Model
public function students()
{
return $this->hasMany('App\Student')->withTimestamps();
}
public function terms()
{
return $this->belongsTo('App\Term')->withTimestamps();
}
Term Model:
public function classrooms()
{
return $this->hasMany('App\Classroom')->withTimestamps();
}
Student model:
public function classrooms()
{
return $this->belongsTo('App\Classroom')->withTimestamps();
}

An many to many relation returns an array which it still does when you define the sudentids ->get() also returns an array only ->first() would not return an array but then you do not get all students.
A variable does not turn in an array automatically making your foreach only return the last value.
So to correctly return the values from the students you would most likely get something like this.
Controller:
// Or even bind the term to the url
$term = Term::findOrFail($id);
return view('students.list',compact("term"));
View:
<!-- You could even remove the classroom name/list around it if you purely want to display all students under the term -->
<li>
#foreach($term->classrooms as $classroom) {
<ul>
Classroom: {{ $classroom->name }}
<li>
#foreach($classroom->students as $student)
<ul>
First name: {{ $student->first_name }}
</ul>
#endforeach
</li>
</ul>
#endforeach
</li>
Another simple way to return all students under a term is using the ->whereHas() in your query doing this would be enough
Controller:
$students = Student::whereHas("classrooms",function($q){
$q->whereHas("terms",function($q){
$q->where("id",$termId);
});
})->get();
return view('students.lists',compact("students"));
View:
<li>
#foreach($students as $student)
<ul>
First name: {{ $student->first_name }}
</ul>
#endforeach
</li>
If you want to return specific classrooms within a term or even a user under both you should create 3 controllers one for each of them (only 2 if you do not want to display students separate) and nest your classrooms under terms so you can simply type /terms/1/classrooms/2/ to get the right classroom or /terms/1/classrooms to get all classrooms under a term.

Related

Laravel Pivot table get value and pass to blade template

i'm trying to get all the Level_id and Term_id on my intermediate table using many to many relationship but i couldn't make it work and i want to pass it to my view using ordered list html.
i always end up with this..Trying to get property of non-object
Controller:
public function get_term_level()
{
$terms=Term::find(1);
foreach ($terms->level as $tm) {
$tm->pivot->Level_id;
}
return view('term_level.index',compact('terms'));
}
Term Model same as with my LevelModel
public function level(){
return $this->belongsToMany(Level::class, 'term_levels')->withPivot('Term_id', 'Level_id');
}
View
#foreach ($terms->pivot as $tm )
<ul>
<li>{{ $tm->Term_id }}</li>
{{ $tm->Level_id }}
</ul>#endforeach
Try this (inside your controller):
foreach ($terms->level()->get() as $tm) {
$tm->pivot->Level_id;
}

How to get data using foreign key in eloquent model?

I have model named 'PropertyLead' as,
class PropertyLead extends Model
{
public function leadPropertyDetails()
{
return $this->belongsTo('App\Models\Property\Property', 'Property_id','id');
}
public function user()
{
return $this->belongsTo('App\Models\Access\User\User','user_id','id');
}
public function propertyRatings()
{
return $this
->hasMany('App\Models\Property\PropertyRating','Property_id','Property_id');
}
}
In my controller I am trying to get data as ,
$leads = PropertyLead::with('leadPropertyDetails','user','propertyRatings')
->get();
Here in $leads variable i am getting all the data that I want but In 'propertyRatings' I am getting user_id and other details. I also want to get the name user who rated that property using that user_id in propertyRatings object. I am really troubled in this query. Thanks in advance.
Use nested eager loading syntax to load nested relationships:
PropertyLead::with('propertyRatings', 'propertyRatings.user', 'leadPropertyDetails', 'user')->get();
Then you be able to display user name with:
#foreach ($leads as $lead)
#foreach ($lead->propertyRatings as $propertyRating)
{{ $propertyRatings->user->name }}
#endforeach
#endforeach

Double foreach loop with where condition in laravel blade

I have relations like this
User->hasMany->reviews
Review->belongsTo->user
Review->hasMany->ReviewAnswer
ReviewAnswer->belongsTo->Review
Now I try to display answers for specific review. My reviewAnswer table looks like:
Id, review ID, text
But the problem is when I do that:
#foreach($user->reviews as $data)
#foreach($data->reviewAnswers->where('review_id', $data->id) as $answer)
{{$answer->text}}
#endforeach
#endforeach
Then reviews displays okay, but I get the same answers for every review. How to repair that?
Make sure to check if all the relationships are correct. In this example, I assume that your models are stored in your app folder.
First, your User model should have reviews
public function reviews() {
return $this->hasMany("App\Review", "user_id", "id");
}
Next, set up your Review model to have answers
public function answers() {
return $this->hasMany("App\ReviewAnswer", "review_id", "id");
}
Then this is how you'll get all users with their respective reviews and answers
$users = User::with("reviews.answers")->get();
Finally, peform the loop in your view
#foreach($users as $user)
#foreach($user->reviews as $review)
#foreach($review->answers as $answer)
#endforeach
#endforeach
#endforeach
Try using the hasManyThrough() option which the eloquent models provide you.
Link: Laravel Eloquent Relations
This means in your case you would add:
class User extends Model {
public function reviewAnswers(
return $this->hasManyThrough(ReviewAnswer::class,Review::class);
)
}
and then simply access it in blade as:
#foreach($user->reviewAnswers() as $reviewAnswer) {
{{$reviewAnswer->text}}
}

A correct query to get data from 3 tables and show it as a single element in laravel?

Suppose I have 3 tables, posts, post_images, and post_links.
post.id is a foreign key in both post_images and post_links.
Each post have multiple images.
I need a data which contains post, its images and its links as single element/array item. If there are 3 posts, I need 3 arrays with each array containing the posts images and links.
My code so far,
$data = DB::table('posts')
->join('post_images','posts.id' ,'=', 'post_images.post_id')
->join('post_links','posts.id' ,'=', 'post_links.post_id')
->select('posts.*')
->get();
with the above query I am getting all the records joined, If i have 3 records with 3 images each, I am getting 9 records, I just need 3 posts with its data as its sub arrays.
Any suggestion?
Here is the PostImage model
class PostImage extends Model
{
public function post() {
return $this->belongsTo(Post::class);
}
}
Here is the PostLink model
class PostLink extends Model
{
public function post() {
return $this->belongsTo(Post::class);
}
}
Here is the Post model
class Post extends Model
{
public function links() {
return $this->hasMany(PostLink::class);
}
public function images() {
return $this->hasMany(PostImage::class);
}
}
In the view you can reach everything you need.
#foreach ($posts as $post)
{$post->title} <br>
#foreach ($post->links as $link)
{$link->url} <br>
#endforeach
#foreach ($post->images as $image)
{$image->src} <br>
#endforeach
#endforeach
And if you want use less queries you could use eager loading to fetch all this data the first time. Eager Loading Laravel
Should look something like this
$posts = Post::with('images','links')->get();
if you already have relation in model you just have to use with method like
$data = PostModel::with('post_images','post_links')->get();
make it dd($data) and look at this. hope it will work.
References: https://laravel.com/docs/5.4/eloquent-relationships#eager-loading

Get posts foreach categories in Laravel

I am using Laravel 4
Here is my Controller:
public function getArticles()
{
$categories = Category::with(['posts' => function($query){
$query->orderBy('updated_at', 'DESC')->take(4)->get();
}])->get();
return View::make('articles', compact('categories'));
}
Here is my View:
#foreach($categories as $category)
<h1>{{$category->title}}</h1>
<ul>
#foreach($category->posts as $post)
<li>
{{ $post->title }}
</li>
#endforeach
</ul>
#endforeach
My Category Model:
class Category extends Basemodel {
public function posts(){
return $this->hasMany('Post');
}
}
And my Post Model:
class Post extends Basemodel {
public function category(){
return $this->belongsTo('Category');
}
}
So it displays correctly my 6 categories (titles), but it only displays 4 posts total, I would like to display the 4 latest posts for each category (24 posts total).
I tried many things, and searched online but couldn't find a way around it.
You can't do that using limit in the eager loading closure, because, as you noticed, it limits the other query, that fetches all the posts.
You can easily get single related model with eager loading for hasMany with a helper relation:
public function latestPost()
{
return $this->hasOne('Post')->latest();
}
but for n related models per each parent, you need a bit more complex solution - take a look at:
n per parent
1 per parent
Maybe you can get use $categories = Category::all() to get all categories first.
foreach $categories and get the latest four posts by $posts=$category->posts
merge the posts array into one array
pass categories and posts to the view.
Cheers.
I hope you can write the correct foreach. And when retrieving the posts, use $category->posts instead of $category->posts(), which results in an error.

Categories