Laravel - Get all records, not just first? - php

today I am facing a problem with Laravel. What I want to do is get every 'stat' value for every record where government_type = higher_government. By the way, I am different types, but this is just one of many.
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->first()->stats;
});
How can I get all the stats for all types instead of just calling ->first() ?
I have tried removing the ->first() but it doesn't do anything except give me this error:
Undefined property: Illuminate\Database\Eloquent\Builder::$stats
stats is a relationship by the way:
public function stats(){
return $this->hasMany('App\Database\Website\User\Roleplay', 'government_id');
}

Try This
\App\YourModelName::select('fields')->where('condition')->get();

If you only want one column from this table, you can use the select function to indicate wich ones you want.
Like so:
<?php
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->select('stats')->get();
});
The collection $higherGovernment will now contain GovernmentRole objects with one parameter, stats.
If you would like this to be an array of only the stats property, you can use collections to pluck this value out of it. Like so:
<?php
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->select('stats')->get()->pluck('stats');
});
Update:
Now that we know that stats is a relation I think the best solution is to just load all GovernmentRole objects and eager load the relation. Then you can display the stats for every GovernmentRole.
You can do it like this:
<?php
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->with('stats')->get();
});
// Just an example on how to get the stats
foreach ($g in $higherGovernment)
echo $g->stats->count();

What you could do is do a select right in the relationship, I think, like this:
public function stats(){
return $this->hasMany('App\Database\Website\User\Roleplay', 'government_id')->select('stats')->get();
}
This would in that case remove the relation, but you'd get the stats. Another way to do it is to just, straight away, get the stats from the relationship like this:
GovernmentRole::where('government_type', 'higher_government')->first()->stats->select('stats')->get();
or if that gives you an error try:
GovernmentRole::where('government_type', 'higher_government')->first()->stats()->select('stats')->get();

Related

How to select only one Column with scope of eloquent model?

I got two tables. Both have a relationship to each other. I´m trying to query both to get the matching results. This results get checked if they also have an column which matches with a parameter value.
I´m trying it with a scope and it work. I only need one column from the second table and I´m trying to use it as column in my first table when I got my result.
So the code works and I got an result but I´m trying to filter to select only one column from the second table.
My code look like that.
My controller:
public function test()
{
$UID='LQuupgYvnuVzbEoguY4TF8bnHUU2';
$event=Events::withState($UID)->get();
echo $event;
}
My model scope function:
public function scopeWithState($query,$UID){
return $query->with(['EventLiked' => function($query) use($UID) {
$query
->where('EventLiked.UID', $UID)
;
}]);
}
My hasMany relationship function:
public function EventLiked()
{
return $this->hasMany(EventLiked::class,'EID','ID')->select('State','UID','EID');
}
I would go for specifying columns inside closure.
New scope:
public function scopeWithState($query,$UID){
return $query->with(['EventLiked' => function($query) use($UID) {
$query
->where('EventLiked.UID', $UID)
->select('State');
}]);
}
Calling scope:
$event=Events::withState($UID)->get();
You're not getting expected results because Laravel splits it into 2 queries:
First, for selecting events.
Then it plucks EID
Second, when it looks for EventLiked where matching ID's is found (from second step) and loads as relationships.
So you want to change select statement only in 2nd query. Not in a first one

How to sum up sub child in laravel and sort

How can I sort or order the result of my query based on the sum of third child of the parent. Please see details below.
What I tried
$childSumTableSorter = function($parents, $column) use ($dir) {
return ($dir == 'asc')
? $parents->get()->sortBy(function($query) {
return $query->item()->inventory->sum('total');
})
: $parents->get()->sortByDesc(function($query) {
return $query->item()->inventory->sum('total');
});
};
Current result
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$inventory
Parent Table
public function item(){
return $this->hasMany(Item::class);
}
Child table
public function inventory() {
return $this->belongsTo(Inventory::class);
}
Inventory class
public function receive_item(){
return $this->hasOne(Item::class);
}
The inventories table has total column which I have to sum up and sort the parent based on the sum of the inventory.
Laravel version: 5.2
Error
The undefined property error is due to that item() returns relationship query, not the result of the relationship. You should perform the query and then get your desired property from retrieved results.
Solution
You can use nested orderBy like as below and perform summation in database layer as stated in orderByRaw method.
$childSumTableSorter = function($parents, $column) use ($dir) {
return ($dir == 'asc')
? Parent::with(['item'=>function($query){
$query->with(['inventory'=>function($query){
$query->orderByRaw('SUM(total) ASC');
}]);
}]);
: Parent::with(['item'=>function($query){
$query->with(['inventory'=>function($query){
$query->orderByRaw('SUM(total) DESC');
}]);
}]);
};
Optimization
As said in laravel doc for has many through relationship, your can query second relationship in a more straightforward way. In your case, you can define inventories method in Parent class.
Parent class
public function inventories(){
return $this->hasManyThrough(Inventory::class, Item::class);
}
By using this method, you can get inventories right from the parent class. Something like $parent->inventories->sum('total')

Laravel modal query

I am trying to get array of related model to my data and it returns null.
Code
public function collection()
{
return Product::with(['allBarcodes' => function ($query) {
$query->select('serial_number');
}])->get();
}
result
Also I tried pluck like $query->pluck('serial_number'); and result was
My real data
the data I suppose to receive is like
[{
"id":1,
"product_id":1,
"serial_number":"5245412185", // I only need this to be return as array
"sold":1,
"created_at":"2020-05-24T04:21:56.000000Z",
"updated_at":"2020-05-24T04:21:56.000000Z"
}]
Any idea?
When you are doing this $query->select('serial_number'); you are only selecting serial_number and not the column that connects both the modals i.e. product_id inside barcodes table.
Do this.
$query->select('product_id', 'serial_number');. However this will return 2 columns. If you want just one then you will have to use collection transform.
$products = $products->map(function ($product) {
$product->allBarcodes->transform(function ($q) {
return $q->serial_number;
});
return $product;
});
Keep me posted in the comments below.

Laravel - Put all records together?

I want to get every 'stat' value from every record in where government_type = 'higher_government' but at the moment my code only gets the stats instances for the first government role it finds, how can I put together all of the stats in some sort of array?
$higherGovernment = Cache::remember('government.higher_government', 1, function() {
return GovernmentRole::where('government_type', 'higher_government')->first()->stats;
});
Stats relationship:
public function government_role()
{
return $this->belongsTo('App\Database\Website\Roleplay\GovernmentRole', 'government_id');
}
Government relationship:1
public function stats(){
return $this->hasMany('App\Database\Website\User\Roleplay', 'government_id');
}
Use pluck()->toArray()
GovernmentRole::where('government_type', 'higher_government')->pluck('stats')->toArray();
This code will return an array of stats properties.
You should be able to use the pluck() method from Eloquent's Collection. https://laravel.com/docs/5.3/collections#method-pluck
Change your query to something like:
GovernmentRole::where('government_type', 'higher_government')
->get()
->pluck('stats', 'government_id');
This will give you a collection containing government_id => stats.
If you want an array rather than a collection, simply add ->toArray()

Laravel Multiple Models Eloquent Relationships Setup?

I have 3 models
User
Pick
Schedule
I'm trying to do something like the following
$picksWhereGameStarted = User::find($user->id)
->picks()
->where('week', $currentWeek)
->first()
->schedule()
->where('gameTime', '<', Carbon::now())
->get();
This code only returns one array inside a collection. I want it to return more than 1 array if there is more than 1 result.
Can I substitute ->first() with something else that will allow me to to return more than 1 results.
If not how can I set up my models relationship to allow this to work.
My models are currently set up as follow.
User model
public function picks()
{
return $this->hasMany('App\Pick');
}
Schedule model
public function picks()
{
return $this->hasMany('App\Pick');
}
Pick model
public function user()
{
return $this->belongsTo('App\User');
}
public function schedule()
{
return $this->belongsTo('App\Schedule');
}
Since you already have a User model (you used it inside you find method as $user->id), you can just load its Pick relationship and load those Picks' Schedule as follows:
EDIT:
Assuming you have a schedules table and your picks table has a schedule_id column. Try this.
$user->load(['picks' => function ($q) use ($currentWeek) {
$q->join('schedules', 'picks.schedule_id', '=', 'schedules.id')
->where('schedules.gameTime', '<', Carbon::now()) // or Carbon::now()->format('Y-m-d'). See what works.
->where('picks.week', $currentWeek);
}])->load('picks.schedule');
EDIT: The code above should return the user's picks which have a schedules.gameTime < Carbon::now()
Try it and do a dump of the $user object to see the loaded relationships. That's the Eloquent way you want.
Tip: you may want to do $user->toArray() before you dump $user to see the data better.
EDIT:
The loaded picks will be in a form of Collections so you'll have to access it using a loop. Try the following:
foreach ($user->picks as $pick) {
echo $pick->schedule->gameTime;
}
If you only want the first pick from the user you can do: $user->picks->first()->schedule->gameTime
I think a foreach loop may be what you're looking for:
$picks = User::find($user->id)->picks()->where('week', $currentWeek);
foreach ($picks as $pick){
$pickWhereGameStarted = $pick->schedule()->where('gameTime', '<', Carbon::now())->get();
}
Try this and see if it's working for you

Categories