I'm having trouble on the eager loading.
Let's say I have models of Members, TrainingCategory, TrainingCategoryResult and Registration
Member Model:
public function registration() {
return $this->hasMany('Registration', 'member_id');
}
public function trainingResults(){
return $this->hasMany('trainingResult', 'member_id');
}
public function trainingCategoryResults() {
return $this->hasMany('TrainingCategoryResult', 'member_id');
}
TrainingCategory Model:
public function trainings() {
return $this->hasMany('Training', 'id');
}
public function trainingCategoryResults() {
return $this->hasMany('trainingCategoryResult', 'category_id');
}
TraningCategoryResult Model:
public function category() {
return $this->belongsTo('TrainingCategory', 'id');
}
public function member() {
return $this->belongsTo('Member', 'id');
}
Registration Model:
public function course() {
return $this->belongsTo('Course', 'course_id');
}
public function member() {
return $this->belongsTo('Member', 'id');
}
I am trying to eager load all the registration info and its related info including the TraningCategoryResult info but I not sure how to get that TraningCategoryResult which required two foreign keys (category_id and member_id), is there any way to do that?
Here is my code atm:
$members= Member::where(function($query) use ($id, $site) {
$query
->where('id', '=', $id)
->where('site', '=', $site);
});
$members= $members
->with('registration.course',
'registration.course.traningCategories',
->get(['member.id']);
Thank you.
This will not work Member::with('categoryResult')->with('registration')->get()
You can make a new relation in Member Model
public function categoryResult()
{
return $this->belongsTo('Category')->with('Registration');
}
//and then call
Member::with('categoryResult')->get();
You could use a few options to achieve that:
OPTION 1: create a variable relationship
Change your relation in the Member model
public function trainingCategoryResults($category_id = null) {
if(empty($category_id))
return $this->hasMany('TrainingCategoryResult', 'member_id');
else
return $this->hasMany('TrainingCategoryResult', 'member_id')
->where('category_id', $category_id);
}
The code above might have limitations and it doesn't take advantage of many laravel features, but it will work.
OPTION 2: Access from relationship
You can keep everything as is, and load as follow:
$members= Member::where(function($query) use ($id, $site) {
$query
->where('id', '=', $id)
->where('site', '=', $site);
})
->where('id', $member_id) // set the id of the memeber
->with(array(
'traningCategoryResults' => function($q)use($category_id){
$q->where('category_id', $category_id); // This makes sure you get only desired results
}
))
In this way you will have only what you need, assuming you know the $category_id
Related
For example I can use:
$address = $user->address
which will return the addresses for the user.
// User.php (model)
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
public function billingAddress()
{
return $this->address()
->where('type', '=', 1)
->where('refer_id', '=', $this->id)
->first();
}
However, I would like to return the BillingAddress for the user depending on this where clause. How do I do it?
EDIT:
If I use this inside... OrderController#index it returns correctly
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')->get();
return new OrderResource($orders);
However, If I change it to:
$orders = Order::with('order_fulfillment', 'cart.product', 'user.billingAddress', 'payment')->get();
return new OrderResource($orders);
I get this error:
Symfony\Component\Debug\Exception\FatalThrowableError
Call to a member function addEagerConstraints() on null
One option is you can use whereHas in your query. For example,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address', 'payment')
->whereHas(
'address', function ($query) {
$query->where('type', '=', 1)
->first();
}
)->get();
return new OrderResource($orders);
This is one option. try to dd($orders) an find if its working.
You had an another option like this, in your model
public function address()
{
return $this->hasMany(Address::class, 'refer_id', 'id');
}
Add relations like
public function billingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 1);
}
And
public function shippingAddress()
{
return $this->hasOne(Address::class, 'refer_id', 'id')->where('type', 2);
}
Then in your query,
$orders = Order::with('order_fulfillment', 'cart.product', 'user.address','user.billingAddress', 'user.shippingAddress', 'payment')->get(); return new OrderResource($orders);
I have three model 1. Task.php 2. Project.php 3. User.php.
Task have a one to many relationship with user and project.php.
Task.php
public function project()
{
return $this->belongsTo(Project::class);
}
public function user()
{
return $this->belongsTo(User::class,'member_id');
}
User.php
public function tasks()
{
return $this->hasMany(Task::class);
}
Project.php
public function tasks()
{
return $this->hasMany(Task::class);
}
Nowi want to retrieve all the task that is associated with users where project id is one (Actually not one, id is passed through url).Here is my attempt
public function taskList($id)
{
$project=Project::with('tasks')->find($id);
$tasks=Task::has('user')->whereHas('project',function($project){
$project->where('id',$project->id);
})->get();
dd($tasks);
return view('leader.tasks',compact('project'));
}
In the above either i give the $id which is i get from the url either $project->id, it always through me the error.Please help me to solve this.
public function taskList($id)
{
$project=Project::with('tasks')->find($id);
$tasks=Task::has('user')->whereHas('project', function($query) use ($project) {
$query->where('id', $project->id);
})->get();
dd($tasks);
return view('leader.tasks',compact('project'));
}
You need to use with() method along with has()
public function taskList($id)
{
$project=Project::with('tasks')->find($id);
$tasks=Task::with('user')->has('user')->whereHas('project', function($query) use ($project) {
$query->where('id', $project->id);
})->get();
dd($tasks);
return view('leader.tasks',compact('project'));
}
This is my Controller method wherein I want to fetch posts by user id.
I also have relationship defined in User model
public function posts()
{
return $this->hasMany('Post','user_id','id');
}
UserController.php
use App\Post;
public function findPostsByUser($id){
$user = User::findOrFail($id);
$posts = $user->posts()->get();
return $posts;
}
But it is giving me 'Post' not found error. Can someone help on this.
In your Post model make sure you have the relation defined like this:
public function user()
{
return $this->belongsTo('App\User');
}
And change your User model to this:
public function posts()
{
return $this->hasMany('App\Post','user_id','id');
}
Change relation method to
use App\Post;
....
public function posts()
{
return $this->hasMany(Post::class,'user_id','id');
}
or
public function posts()
{
return $this->hasMany('App\Post','user_id','id');
}
If you wont to get only posts that case use this
public function findPostsByUser($id){
$posts = Post::where('user_id', $id)->get();
return $posts;
}
The second solution has 1 query, but first solution has 2 query in db.
Also you can do it this way
public function findPostsByUser($id){
$posts = Post::whereUserId($id)->get();
return $posts;
}
I want to get all the books under a certain category. The category has many subjects and books are linked to subjects.
My code:
class BookCategory extends Model {
public function subjects() {
return $this->hasMany('BookSubject', 'category_id', 'id');
}
public function getBooksAttribute() {
return Books::whereHas('subjects', function ($query) {
return $query->join('book_category', 'book_category.id', '=', 'book_subject.subject_id')
->where('book_category.id', $this->id);
})->get();
}
}
and my Books model:
class Books extends Model {
public function subjects() {
return $this->belongsToMany('BookSubject', 'book_by_subject', 'book_id', 'subject_id');
}
}
If I do:
$cats = \App\Models\BookCategory::all();
foreach ($cats as $c) {
echo $c->books->count();
}
It's always returning 0 for all the rows. What I'm I doing wrong?
I believe the problem is in your subquery:
return $query->join('book_category', 'book_category.id', '=', 'book_subject.subject_id')
->where('book_category.id', $this->id);
I'm pretty sure book_subject.subject_id should be book_subject.category_id
Hard to tell without seeing your db schema.
I can get the list of Likes that User 1 did on a Media from Store 1
$medias = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get();
But i need to retrieve the list of medias, so i tried
$medias = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get()->media;
But then i get
Undefined property: Illuminate\Database\Eloquent\Collection::$media
class User extends Model
{
public function likes()
{
return $this->hasMany('App\Like');
}
}
class Media extends Model
{
public function store()
{
return $this->belongsTo('App\Store');
}
public function likes()
{
return $this->hasMany('App\Like');
}
}
class Like extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
public function media()
{
return $this->belongsTo('App\Media');
}
}
This is because you get media separate for each like. You should use:
$likes = User::find(1)->likes()->with('media')->whereHas('media', function($q) {
$q->where('store_id', '=', 1);
})->get();
foreach ($likes as $like) {
$media = $like->media;
// now you can do something with your media
}
EDIT
If you want to get only media, you should add to your User model the following relationship:
public function medias()
{
return $this->hasManyThrough('App\Media','App\Like');
}
Now to get your media, you should do :
$medias = User::find(1)->medias()->where('store_id', '=', 1)->get();
Made it work with
$store->medias()->whereHas('likes', function($q) use($user) {
return $q->where('user_id', '=', $user->id);
});