Laravel fill empty days in collection of stdclass - laravel

I have a query that return a collection of stdclass objects with 'data' and 'day properties. Returns a collection, with all the days that return data, but not those with no lines
$reservations = DB::table('reservation')->selectRaw("
count(id) AS data,
DAY(created_at) AS day
")
->where( DB::raw('YEAR(created_at)'), '=', '2023')
->where( DB::raw('MONTH(created_at)'), '=', '12')
->groupBy('day')
->get();
I need to create an array with values for each day of the month containing only the data field. If the day does not exist in the collection, assign it a 0.
$array = [10, 23, 12, 0, 10...];
I thought about making a loop for each day with CarbonPeriod, but inside I have to make another loop with the result to check if there is a match, add the value, and if not add the 0. Is there a collection method or other way to facilitate this?
foreach (CarbonPeriod::create($initmonth,'1 day',$lastDayMonth) as $key => $day) {
foreach ($reservations as $key => $value) {
//here I'm trying to find the match
if($day->day == $value->day) $array[] = $value->data // else ???
}
}

Related

Eloquent count of single object is wrong

I have a method that only changes one small thing based on if an object of one item is passed through, vs a single object, but the count() is wrong on single items...
Assuming I have 25 entries in my table...
$contacts = Contact::all();
dd("Count = " . $contacts->count());
Count = 25
$contact = Contact::where('individual_id', '=', $id)->first();
dd("Count = " . $contact->count());
Count = 25
Why is it showing a count of objects in the table instead of just the number that were returned?
Laravel v9.19
PHP v8.0.2
Let's analyze your code:
$contact = Contact::where('individual_id', '=', $id)->first();
$contact will either be an instance of your Contact model, or null.
If it is a Model instance, then calling ->count() is basically calling this:
Contact::count(); // 25
$contact = Contact::where('individual_id', '=', $id)->first();
$contact->count() == Contact::count(); // true
Models have a count() method, so you can do things like $model->where(...)->count(), etc.
If $contact is null, then your code will fail:
$contact = null;
$contact->count(); // Error: `null->count()` is invalid.
So, for your case, there is basically no reason to ever call Contact::where(...)->first()->count(), as that will not return 1, unless there is legitimately 1 record in your contacts table (pretty scary false-positive).
The other answer suggests to use ->get(), which is valid, as a Collection has a count() method that outputs the length of the underlying Array:
$contact = Contact::where('individual_id', '=', $id)->get();
$contact->count(); // 1
It will return 1, unless you have multiple records in the database where individual_id is equal to $id.
So, TL;DR: ->first() returns a single Contact instance or null and shouldn't use ->count() after, while ::all() or ->get() returns multiple and can use ->count() after.
When you are using first() it is returning MODEL.You have to use get() so that you can use count() as get() will return collection.
$contact = Contact::where('individual_id', '=', $id)->get();
dd("Count = " . $contact->count());
It will give you the desired result.
also you can do this...
$count = Contact::where('individual_id', '=', $id)->count();
dd("Count = " . $count);

Filter record through dates not working laravel

I have a expiry_date (type=date) column in my table
$currentDate = date('Y-m-d');
$Data = Post::whereDate('expiry_date','<=',$currentDate)->where(['status' => 'active'])->orWhere(['p_id' => 3])->select('id','title','status','p_id','expiry_date')->orderBy('id', 'DESC')->get();
i want to filter data if current date is greater than expiry date then those record should not be shown but in my scenario i'm still getting record.
Any solution Thanks.
You must group orWhere clause in closure. Grouping in closure is like () in real query.
$Data = Post::whereDate('expiry_date','<=',$currentDate)
->where(function($query){
return $query
->where(['status' => 'active'])
->orWhere(['p_id' => 3]);
})
->select('id','title','status','p_id','expiry_date')
->orderBy('id', 'DESC')
->get();
But, because I don't know your project - i may wrong with grouping.

Count records by field in laravel model

I'm looking the best way to get and array that count existent rows of some eloquent model by a certain field. Guest an Installation model with a type field. Right now Iam using this approach to do it
$typeCount = Installation::select('type', DB::raw('COUNT(*) as count'))
->groupBy('type')
->get()
->mapWithKeys(function($item) {
return [$item['type'] => $item['count']];
})->toArray();
and $typeCount will return an array like this
[
"contrib" => 2,
"official" => 1,
]
Is there a better way or an elegant one????
According to pluck method:
Collection pluck(string $column, string|null $key = null)
Laravel will use the column value of second parameter as key, the column value of first parameter as value:
$typeCount = Installation::select('type', DB::raw('COUNT(*) as count'))
->groupBy('type')
->pluck('count', 'type')
->toArray();

How do I add multiple where conditions in query dynamically using query builder

I have array of parameters and they are coming dynamically I want to make query based on parameters.
For Example
$arr Array of parameters
(
[shareName] => First Item
[sharePrice] => 100
)
The Query have to add where clause dynamically
foreach($arr as $k => $v)
{
$data = DB::table('itemstable')->where($k, $arr[$k])->where($k, $arr[$k])->get();
}
how do I know and add two where conditions ?
$query->where([
['column_1', '=', 'value_1'],
['column_2', '<>', 'value_2'],
[COLUMN, OPERATOR, VALUE],
...
])

Column value as index to generate 2 level collection

I am trying to get a collection which has index as column values.
First level will have product_id as index and second level will have stock_date.
$data = Model::select('column1', 'product_id', 'stock_date')
->where('some condition')
->get();
$data = collect($data)->groupBy('product_id');
With the code above, I get the collection with product_id as the indexes.
I need the data of each product indexed by stock_date
If, for example, for product_id - 1, I have multiple records, I tried
$product_details = collect($data[1])->groupBy('stock_date');
But it does not index the records with stock_date further.
Need help to index them with stock_date.
possible solution.
// first index grouped by product_id
$original = Model::select('column1', 'product_id', 'stock_date')
->where('some condition')
->get()
->groupBy->product_id;
$final = collect();
// iterate through each group and
// group inner collection with 'stock_date'
// and put them back in an collecion
foreach($original as $key => $value) {
$final->put($key, $value->groupBy->stock_date);
}
Do you means these records are nested by stock_date,
and then stock_dates are nested by product_id
If it is, please try this below, the collect() method make all nested records becomes collection, you don't need to use collect() again.
$data = Model::select('column1', 'product_id', 'stock_date')
->where('some condition')
->get();
$data = collect($data)->groupBy('product_id');
$nested_products = [];
foreach($data as $product_id => $items) {
$nested_products []= $items->groupBy('stock_date');
}
Or you can try this line, it's more elegant:
collect($data)->groupBy('product_id')->transform(function($item, $k) { return $item->groupBy('stock_date');})

Resources