Get all elements of array in query laravel - php

I am trying to loop in an array but when it comes to the query it gets only the first element, so a little help would be very important.
$data = Offers::whereIn('id_business', $business_id_array)
->where([
'visible' => 'yes',
'delete' => 'no'
])
->where('end_date', '>=', date('Y-m-d h:m:i'))
->orderBy('id', 'desc')
->get();
$data=array($data);
foreach($data as $key => $item) {
$offers = DB::select('the data i need to get WHERE o.`id` = ' . $item[$key]['id']);
}
and this is my problem in here, It gets only the id of the first element
o.`id` = ' . $item[$key]['id']

because you have return the view in side the foreach loop, so it only loop through the first item and return. What you can do with this case is
$data = Offers::whereIn('id_business', $business_id_array)...->get()->toArray();
$offers = array_map(function($item){
$offer = DB::select('the data i need to get WHERE o.`id` = ?', [$item->id]);
return $offer;
},$data);
return view(....,['offers' =>$offers]);

First, you do not need to cast the $data to an array - it will get returned as a collection, which you can iterate through like an array. So you'll be able to use something like this
$offers = Offers::whereIn('id_business', $business_id_array)...->get();
foreach ($offers as $offer) {
$moreData = DB::select('the data i need to get WHERE o.`id` = ?', [$offer->id]);
}

This looks like you are using the id from one table, to get the associated data from another table.
Should there not be a relationship in place, between the two tables?
The answer from #Chris G looks correct, maybe dd($offers) to be certain what is in there.
Mick

Related

Order and Sub Order collection - laravel 7 (Simple)

lets say I have a collection of users Users::all()
I would like to take sort/order it like such Users::all()->sort('created_at', 'DESC')
then I would like to sub order it by an array like [1,5,3,9,4,8] so perhpas a call like this Users::all()->sort('created_at', 'DESC')->sortBy("id", [1,5,3,9,4,8])
Any Advice?
Edit 1
I have found this, is this correct to use?
$ids = collect([1,5,3,9,4,8]);
$users = Users::all()->sort('created_at', 'DESC');
$users = $ids->map(function($id) use($users) {
return $users->where('cat_id', $id)->first();
});
I think you could just invoke orderBy() twice.
$ids = [1,5,3,9,4,8];
$users = Users::all()
->orderBy('created_at', 'desc')
->orderBy($ids)
->get();
Does this answer your question?
You can use whereIn like this probably:
$ids = [1,5,3,9,4,8];
$users = Users::all()
->orderBy('created_at', 'desc')
->whereIn('cat_id', $ids)
->get();
https://laravel.com/docs/9.x/queries#additional-where-clauses
The whereIn method verifies that a given column's value is contained within the given array
So I found a solution.
$ids = json_decode($interview->question_ids ?? '[]');
if(count($ids) == 0){ // if empty create new id array and save to DB
$ids = collect(questions::all()->where('interview_id', $interview->id)->pluck('id')->toArray());
$interview->question_ids = json_encode($ids);
$interview->save();
}
$questions = questions::all()->where('interview_id', $interview->id)->sortBy([
['order_timestamp', 'asc'],
['created_at', 'asc'],
]);
$questions = $ids->map(function($id) use($questions) {
return $questions->where('id', $id)->first();
});
$questions = $questions->flatten();

Laravel: Querying JSON column containing array, expecting similar results to "whereIn"

I have a database column called support_tags. This is a jsonb column containing a simple array that looks like:
[
"caring",
"budgets",
"careers_employment",
"addictions"
]
I am attempting to query this column using the following:
$services = \App\Models\Service::where("status", "accepted")->whereRaw("JSON_CONTAINS(support_tags, '" . json_encode($categories) . "')")->get();
This doesn't retrieve the results I am hoping for/expecting. If I send the following array:
[
"caring",
"smoking"
]
The results I get back are services that contain all array elements. I need this to work more like a whereIn, in that not all array values need to be present in the database column, but one or more. If anyone knows of a way to do this I'd be very grateful. Thanks.
you can use these eloquent methods: ->whereJsonContains() and ->orWhereJsonContains()
your query will be like this:
$services = \App\Models\Service::where("status", "accepted")
->where(function($query) {
$query->whereJsonContains('support_tags', 'smoking')
->orWhereJsonContains('support_tags', 'caring');
});
Just before I accept the other answer to this question, I thought it may be useful to share my implementation of this which is based on the accepted answer This does the trick:
$categories = request()->infoAdviceCategories;
$services = [];
if (count($categories)) {
$services = \App\Models\Service::where("status", "accepted")->whereJsonContains("support_tags", $categories[0]);
foreach ($categories as $category) {
if ($category !== $categories[0]) {
$services->orWhereJsonContains("support_tags", $category);
}
}
$services = $services->get();
}
return $services;

How to iterate a foreach loop starting from the last element in php?

I have a resultset fetched from database in laravel through this code.
$products = Product::whereNull('box_size')->get();
There are about 18000 objects in $products variable. I need to get the previous object of the last object from the list. How can I do so? Is there any way to iterate through a foreach loop from the last of a resultset?
If you only need that one record, be more precise in your query to avoid a lot of extra data loading and processing:
$products = Product::whereNull('box_size')
->orderBy('created_at', 'DESC')
->skip(1)
->take(1)
->get();
You can do it from your model easily (for last 10 query) :
$products = Product::orderBy('id', DESC)->whereNull('box_size')->take(10)->get();
For just last query :
$products = Product::orderBy('id', DESC)->whereNull('box_size')->first();
Or, With foreach loop get only 10 result :
#php
$i= 0;
#endphp
#foreach($all as $data) {
$i++;
include $data->name;
if($i == 10) break;
}
#endforeach
A mentioned above you can do so through your model:
$products = Product::latest()->whereNull('box_size')->get();
This will give you eloquent for all products sorted by DESC in column created_at.
You can sort the results with descend order, and then the second item is what you want:
$products = Product::orderBy('id', DESC)->whereNull('box_size')->get();
$item = $products[1];
Directly access the item from the Collection object:
$products = Product::whereNull('box_size')->get();
$item = $products->get($products->count() - 2);
//or pop
$products->pop()
$item = $products->pop();

push data in to a multidimensional array in laravel php

I want to create a multidimensional array to save the data according the date and a category as follow. Then i need to display this data in my blade view?what can i do to achieve this.
'2012-05-05' => array(
'suspension' => 52,
'transmission' => '58'
),
'2012-05-05' => array(
'suspension' => 44,
'transmission' => 21
I have done the following in my controller i want a $reportData variable to load the data.
public function loadReports(Request $request)
{
$data = ['2012-05-05','2012-05-06'];
$salesItems = array();
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
$categories = App\Categories::all();
foreach ($data as $date) {
foreach ($categories as $category) {
$categoryValue = 0;
foreach ($salesItems as $salesItem) {
if ($date == $salesItem->order->orderDate) {
$categoryValue += $categoryValue + $salesItem->subTotal;
}
}
//error appears as illegal offset type
$reportData[$date][$category]=$categoryValue;
}
}
return View::make('Retailer/reports')->with('categories', $categories)->with('reportData', $reportData);
}
I haven't tested it but looking at your code it seems that you're passing an object as array index key as 2nd level array index:
$reportData[$date][$category] = $categoryValue;
^^^^^^^^^ this is an object
Dump your $category in the foreach loop & check if that is the case: dd($category)
If you're using Eloquent & your Categories Model has a name property, you'll probably want to take each category name as index value:
$reportData[$date][$category->name] = $categoryValue;
The error is occurring due to the fact that you are trying to use an Object as the array's index.
As per the laravel documentation (https://laravel.com/api/4.2/Illuminate/Database/Eloquent/Model.html#method_all) the all method you called here '$categories = App\Category::all();' would have returned an Eloquent Collection.
So when you iterated over the $categories array and referenced $category, you were referencing an object. In PHP an array can only be indexed by either an integer or a string. So you need to change the line of code where the error is to this
$reportData[$date][$category->someVar] = $categoryValue;
Where someVar is the name of a variable on the Eloquent model Category that references its name, such as 'suspension' etc.
While it doesn't answer your question you could use the Eloquent engine to make your life easier:
$orderItems = OrderItem::with('spare', 'order')->get();
foreach ($orderItems as $key => $orderItem) {
if ($orderItem->spare->retailer_id == Auth::user()->id) {
array_push($salesItems, $orderItem);
}
}
can be simplified (and made more efficient) with:
// Store the uid to save the call.
$user_id = Auth::user()->id;
// Apply the condition to the Eloquent query.
$orderItems = OrderItem::with(['spare' => function($query) use ($user_id) {
return $query->where('retailer_id', '=', $user_id);
}, 'order'])->get();
The other answers are correct, but you probably also want to initialise the $reportData array as before you start working with it.

Laravel - get the only item properties from collection without the foreach loop

I wonder is there a way to get an only item properties without a foreach loop. Since I have a query where in most of the cases there will be only one item in collection, and I need to change the status in the pivot table for only that case, I wonder is there some elegant way of doing this without the foreach loop. This is the case I am talking about:
$opponents = $quiz
->players()
->where('id', '!=', $player->id)
->get();
if ($opponents->count() < 2) {
$quiz->status = 'finished';
$quiz->save();
foreach ($opponents as $opponent) {
$quiz->players()->updateExistingPivot($opponent->id, ['status' => 'dropped']);
}
}
You can use the function first() like this:
$quiz->players()->updateExistingPivot($opponents->first()->id, ['status' => 'dropped']);

Categories