Laravel limit relation data - laravel

I have the following eloquent query:
$move['topUsers'] = UserMoves::where('move_id',$move->id)
->with(array('userBase'=>function($query){
$query->select('id','name')->orderBy('power','desc')->take(3);
}))->get();
The query works fine but the ->take(3) doesn't. I get all of the relation results while I'm looking only for the first 3, ordered by power column.
the ->orderBy('power','desc')->take(3) is not working in the $query.
How I can limit the realtion data to 3 results ordered by the power column?

Try method from this article which is exactly about limiting relationship while eager loading:
// New relationship
public function mostPowerful()
{
return $this->hasOne('userBase')->orderBy('power', 'desc');
}
// Get data
$move['topUsers'] = UserMoves::where('move_id',$move->id)
->with('mostPowerful')
->take(3)
->get();

Try this.
$move['topUsers'] = DB::table('your_table_name')
->where('move_id', $move->id)
->select('id','name','power')
->orderBy('power', 'desc')
->take(3)
->get();
Hope this work.

Without array:
$topusers = UserMoves::where('move_id',$move->id)
->with(['userBase'=>function($query){
$query->select('id','name')->orderBy('power','desc')->take(3);
}])->get();

Related

How do I search by a table included using with() statement

I am trying to search with a column on a connected table using with. According to laravel the following should work.
$lineItems = Invoice::with(['invoiceHeader' => function ($query) {
$query->where('community_id', '=', 1);
}, 'invoiceLineItems'])
->limit(10)
->get()
->toArray();
However, I don't get anything from the invoiceHeader table and I get all the invoices available. If I take out the function I get the same but with invoiceHeader's table values showing up.
$lineItems = Invoice::with(['invoiceHeader', 'invoiceLineItems'])
->limit(10)
->get()
->toArray();
It seems I might be doing something of a right join where I get all the Invoices but then only the invoiceHeader values when applicable to the foreign key.
Edit:
I put ->toSql(); after the limit() and it shows I only get the following.
"select * from `invoice` limit 10"
You should use whereHas mixing with with:
$lineItems = Invoice::with(['invoiceHeader', 'invoiceLineItems'])
->whereHas('invoiceHeader', function ($query) {
return $query->where('community_id', 1);
})
->limit(10)
->get()
->toArray();

Join Laravel tables

I have got three tables Kudos, Kudoscategories, and specialpost. I need to get the data from those tables and check the post id using a where condition.
I have attached the database table screenshot here
I already tried this, but it's not getting any result.
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
What I need to do is get the results using below where condition newsfeed_special_posts.main_post_id = kudos.spid
You must add another join with newsfeed_special_posts.
The query will be like,
$results = DB::table('kudos')
->select('kudos.description','kudoscategory.catname','kudoscategory.image','kudos.spid')
->join('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->join('newsfeed_special_posts', 'newsfeed_special_posts.main_post_id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
Though this is not a good practice for laravel. using laravel eloquent relationships will be more efficient for these results.
https://laravel.com/docs/5.8/eloquent-relationships
you can still do it this way. still efficient to avoid sql injection since you are getting all the record from the 3 tables. seeing your table above, its not properly normalised. anywaye try this.
$results = DB::table('kudos')
->leftjoin('kudoscategory', 'kudoscategory.id', '=', 'kudos.categoryid')
->leftjoin('newsfeed_special_posts', 'newsfeed_special_posts.id', '=', 'kudos.spid')
->where('kudos.spid', '=', $post_id)
->first();
return $results;
you can try this code
at first, create model Kudos,KudosCategory,NewsfeedSpecialPosts
Kudos Model
public function kudoscategory_dta()
{
return $this->belongsTo('App\Model\KudosCategory','categoryid');
}
public function newsfeed_special_posts_dta()
{
return $this->belongsTo('App\Model\NewsfeedSpecialPosts','spid','main_post_id ');
}
controller
Kudos::with('kudoscategory_dta','newsfeed_special_posts_dta')->first();

Laravel Eloquent Pivot Tables filtered by pivot column on object collection

I've a problem and searching for a nice solution for it.
I've these db tables:
game_objects
game_object_attributes
game_object_game_object_attribute (pivot)
GameObject.php:
public function gameObjectAttributes()
{
return $this->belongsToMany('App\Models\GameObjectAttribute')->withPivot('value')->withTimestamps();
}
GameObjectAttribute.php:
public function gameObjects()
{
return $this->belongsToMany('App\Models\GameObject');
}
Now I'm trying to get all GameObject of an GameObjectType and filtering the result with pivot column 'value'.
$this->model->where('name', $gameObjectTypesEnum)->first()->gameObjects()->join('game_object_game_object_attribute', 'game_objects.id', '=', 'game_object_game_object_attribute.game_object_id')->where('value', '=', '4')->get());
I've used here an join but is there a way to do it with eloquent's relation?
This is returning me all GameObjects of type 'troops':
$this->model->where('name', $gameObjectTypesEnum)->first()->gameObjects()->get();
the 'gameObjects()' returning me a collection and here I can't call something like
$this->model->where('name', $gameObjectTypesEnum)->first()->gameObjects()->withPivot('value', 3)->get();
OR
$this->model->where('name', $gameObjectTypesEnum)->first()->gameObjects()->gameObjectAttributes->wherePivot('value', 3)->get();
Here I can iterate through collection 'gameObjects()' and checking with foreach if the pivot has value = 3 but there must be a better solution than this. I'm new to laravel..
Additionally
I try to get
Get all GameObjects by an GameObjectType => returning a collection**
GameObjectType::where('name', $gameObjectTypesEnum)->first()->gameObjects()
Then I try to filtering trough pivot to get only GameObjects with given GameObjectType and with pivot value e.g. 3.
->join('game_object_game_object_attribute', 'game_objects.id', '=', 'game_object_game_object_attribute.game_object_id')->where('value', '=', '4')->get());
I'm doing something wrong or this is not possible to do it with Eloquent :-(
Thank you all in advance.
Best regards
You can do like this
$gameObjects = GameObject::where('name', $gameObjectTypesEnum)->whereHas('gameObjectAttributes', function($query)
{
$query->where('value', 3);
})->get();
If I didn't misundertand it,
->wherePivot('value',4)
addition to your query is the eloquentish way of that join.

Where clause inside whereHas being ignored in Eloquent

Im trying to make a query using whereHas with eloquent. The query is like this:
$projects = Project::whereHas('investments', function($q) {
$q->where('status','=','paid');
})
->with('investments')
->get();
Im using Laravel 5.2 using a Postgres driver.
The Project model is:
public function investments()
{
return $this->hasMany('App\Investment');
}
The investments model has:
public function project() {
return $this->belongsTo('App\Project');
}
The projects table has fields id,fields...
The investments table has the fields id,project_id,status,created_at
My issue is that the query runs and returns a collection of the projects which have at least one investment, however the where clause inside the whereHas is ignored, because the resulting collection includes investments with status values different than paid.
Does anyone has any idea of what is going on?
I believe this is what you need
$projects = Project::whereHas('investments', function($q) {
$q->where('status','=','paid');
})->with(['investments' => function($q) {
$q->where('status','=','paid');
}])->get();
whereHas wil check all projects that have paid investments, with will eagerload all those investments.
You're confusing whereHas and with.
The with method will let you load the relationship only if the query returns true.
The whereHas method will let you get only the models which have the relationship which returns true to the query.
So you need to only use with and not mix with with whereHas:
$projects = Project::with(['investments' =>
function($query){ $query->where('status','=','paid'); }])
->get();
Try like this:
$projects = Project::with('investments')->whereHas('investments', function($q) {
$q->where('status','like','paid'); //strings are compared with wildcards.
})
->get();
Change the order. Use with() before the whereHas(). I had a similar problem few weeks ago. Btw, is the only real difference between the problem and the functional example that you made.

Eloquent constraint by relationship

I get my data as follows: $completes = Complete::with(['answers', 'survey.location'])->orderBy('created_at', 'DESC')->get();
How can I get all completes where survey.location = 1?
I've tried doing it like Location::where()->with('completes') etc but I need it to be ordered by completes without getting grouped by location
Try this :
$completes = Complete::with('answers')
->whereHas('survey', function ($query) {
$query->where('location','=',1);
})
->orderBy('created_at', 'DESC')->get();
For more details take a look in the Doc in the Constraining Eager Loads section :)

Resources