Fetch data nested relations eloquent with() in Laravel - php

I have a model file "Student" that contains the relation :
public function implementations()
{
return $this->hasMany(Implementation::class);
}
In my Implementation model, I have theses relations :
public function score()
{
return $this->belongsTo(Score::class, 'id', 'implementation_id');
}
public function project()
{
return $this->belongsTo(Project::class);
}
I would like to retrieve a table with all its data.
I tried this
public function getStudents($id)
{
$event = Event::where('id', $id)->first();
$data = $event->students()->with('implementations')->get();
return response()->json($data);
}
It works. But I do not have the result I would like. I would also like to recover the implementations data with theproject and score relationships
I tried that but it does not work
public function getStudents($id)
{
$event = Event::where('id', $id)->first();
$data = $event->students()->with('implementations')->with('project', 'score')->get();
return response()->json($data);
}
Thank you very much for your help!

Have you tried Event::with('students', 'students.implementations') yet? You can eager load relations of relations using the dot notation.

Related

Returning furnitures of each Person in the controller

I have this controller and I would like to return each person's furniture. This 'chilren' method didn't work. The relationship between the two 'one to many' is working correctly. It isn't mandatory to use children method. Any resource to solve the problem is accetable.
IMPORTANT: Laravel Version 5.8
PersonController.php
public function showPersonFurnitures($id) {
$person = Person::findOrFail($id);
$furnituresOfEachPerson = $person->childs();
return response()->json($furnituresOfEachPerson);
}
you are not triggering the query :
use this (with eager loading)
public function showPersonFurnitures($id) {
$person = Person::with('childs')->findOrFail($id);
$furnituresOfEachPerson = $person->childs;
return response()->json($furnituresOfEachPerson);
}
or this : (calling the relationship directly)
public function showPersonFurnitures($id) {
$person = Person::findOrFail($id);
$furnituresOfEachPerson = $person->childs()->get();
return response()->json($furnituresOfEachPerson);
}
or third option if the person->childs() relationship is a belongsTo :
public function showPersonFurnitures($id) {
$furnituresOfEachPerson = Child::where('person_id', $id)->get();
return response()->json($furnituresOfEachPerson);
}

Laravel - Model Eloquent without relationships

i trying to load all rows from a model without the relationship.
The attributes $with it not event set on my Event model but when i do
$events = Event::all();
all my relationship are loaded, and i can see all the query with the dbquerylog.
i don't understand why theses relationship are loaded,
Please help me !
Thanks you.
I'm using Laravel 8.
here's an example.
class Event extends Model {
public function items() {
return $this->hasMany(Item::class);
}
public function items2() {
return $this->hasMany(Item2::class);
}
public function items3() {
return $this->hasMany(Item3::class);
}
public function items4() {
return $this->hasOne(Item4::class);
}
}
$events = Event::all();
If you have a single instance of a model object, you can do:
$obj->withoutRelations();
As laravel documentations says you can use without: https://laravel.com/docs/8.x/eloquent-relationships
Model
protected $with = ['item1','item2','item3','item4'];
Controller
$events = Event::without(['item1','item2','item3','item4'])->get();
I met this problem one day, and it turned out that I was using relation in scope method. Because of this relation values were added to response.
Check out this example:
class Event extends Model {
public function items() {
return $this->hasMany(Item::class);
}
[...]
public function scopeItemsGreen() {
return $this->items->every(function ($item) {
return $item->color == 'green';
});
}

the relation is not appending to the model in laravel

i want to append a relation to my model in laravel i know its possible with resource but i need it to be appened to model so here its like below what i do :
protected $appends = ['accommodation_rooms'];
public function getAccommodationRoomsAttribute(){
return $this->accommodationRooms();
}
and my relation is :
public function accommodationRooms()
{
return $this->Hasmany(AccommodationRoom::class);
}
but when i run my api it returns null but when i call the relation it has the relation and it has no problem . any idea what i am doing wrong ??
EDIT
$data = Accommodation::with('city', 'accommodationFacilities', 'gallery')
->where('is_deleted', 0)->Paginate(env('PAGINATE_NUMBER'));
return $data;
return $this->accommodationRooms() will return an instance of query builder. That is probably why it was showing empty.
Change it to
public function getAccommodationRoomsAttribute(){
return $this->accommodationRooms;
}
Call it without ()
public function getAccommodationRoomsAttribute(){
return $this->accommodation_rooms;
}
And update your relation to:
public function accommodationRooms()
{
return $this->hasMany(AccommodationRoom::class);
}
And make sure you have accommodation_id column in your accommodation_rooms table

Cache Eloquent Relationship query

How can I cache this Eloquent query:
dd($user->roles);
Because above will somehow trigger the $user->roles() query I assume.
I have tried with this:
public function roles() {
return \Cache::remember('user_' . $this->id . '_roles', 10, function() {
return $this->hasMany('App\Role');
});
}
But it does not work, because it has to return a array, not eloquent query.
Any suggestions?
Here is my approach:
public function bookmarks(): HasMany
{
return $this->hasMany(Bookmark::class);
}
protected function getBookmarksCacheKey(): string
{
return sprintf('user-%d-bookmarks', $this->id);
}
public function clearBookmarksCache(): bool
{
return Cache::forget($this->getBookmarksCacheKey());
}
public function getBookmarksAttribute(): Collection
{
if ($this->relationLoaded('bookmarks')) {
return $this->getRelationValue('bookmarks');
}
$bookmarks = Cache::rememberForever($this->getBookmarksCacheKey(), function () {
return $this->getRelationValue('bookmarks');
});
$this->setRelation('bookmarks', $bookmarks);
return $bookmarks;
}
You can't store a relationship in the cache. You need to cache the actual data retrieved from the database. So you'll have something like this:
public function roles()
{
return \Cache::remember('user_' . $this->id . '_roles', 10, function()
{
return $this->hasMany('App\Role')->get()->toArray();
});
}
And now you have to access it as a method, not a property, because it's not returning a relation anymore (and Eloquent would throw an exception):
$user->roles();
Now you should get an array as you want.
If you want to cache user together with its roles you can do it this way:
$user = User::find(1);
$user->load('roles');
Cache::put('users_'.$user->id, $user, 10);
I don't know why, but you need to use load here instead of with. If you used with you would get error that you cannot cache PDO instance.

Laravel 4:: Returning models and its relationship

I would like to return the model and part of its relationship
EX::
User model
public function comments()
{
return $this->hasMany('comments');
}
Comments model
public function user()
{
return $this->belongsTo('user');
}
Can I return all comments and the user's name associated with the comment?
The desired effect is
$comment = Comments::find($id);
$comment->user;
return $comment;
This will return the one comment and the associated user full model. I just need the name of the user. And this does not works if I call Comments::all()
Thank you in advance.
You're looking for Eloquent's Eager Loading
Assuming your Comments model has a method user():
public function user()
{
return $this->belongsTo('User');
}
You should be able to do this in your controller:
$comments = Comments::with('user')->where('post_id', $post_id);
// Return JSON, as is Laravel's convention when returning
// Eloquent model directly
return $comments;
You can do the opposite as well:
Assuming your User model has a method 'comments()', like so:
public function comments()
{
return $this->hasMany('Comment');
}
Inside of your controller, you should be able to do the following, assuming your have the $id of the user available:
$user = User::with('comments')->find($id);
// Return JSON, as is Laravel's convention when returning
// Eloquent model directly
return $user;

Categories