How to convert lavavel collection to square bracket collection - laravel

I have laravel livewire collection as below.
[
{
"date":"2021.09.01-0:00",
"open":110.177,
"close":110.175,
"low":110.172,
"high":110.18
},
{
"date":"2021.09.01-0:01",
"open":110.175,
"close":110.171,
"low":110.169,
"high":110.175
},
{
"date":"2021.09.01-0:02",
"open":110.171,
"close":110.173,
"low":110.17,
"high":110.176
}
]
I would like to convert them into form of square bracket collection without key name as below .
$data = [
['2021.09.01-0:00',110.177,110.175,110.172,110.18],
['2021.09.01-0:01',110.175,110.171,110.169,110.175],
['2021.09.01-0:02',110.171,110.173,110.17,110.176]
];
Any advice or guidance on this would be greatly appreciated, Thanks.

You can use collection map method:
The map method iterates through the collection and passes each value to the given callback. The callback is free to modify the item and return it
https://laravel.com/docs/8.x/collections#method-map
$expectData = $collection->map(fn($item) => [$item-> date, $item->open,...])

I am not sure what the original data is but you can map over the collection and pull the values; if Eloquent Models:
$data->map(fn ($v) => array_values($v->toArray()))
Would depend upon how you got that original Collection for how it would end up in this scenario.
If you need to restrict what attributes and the order of them returned you can use only on the model:
fn ($v) => array_values($v->only(['date', ...]))

Related

append to a field of array with eloquent

I have an application with laravel and mongodb. With elequent iam trying to append a new value to an array stored in a field.
So this is an example of a document. Iam trying to append a new value to the projects field.
{
"_id":{
"$oid":"5f80513714450000a6007c90"
},
"organization_id":"5f80304214450000a6007c81",
"user_id":"5f80513714450000a6007c8f",
"status":true,
"role_id":"5c148783fe412ba8333074ec",
"company_id":"5f80511f14450000a6007c8e",
"updated_at":{
"$date":"2020-11-09T18:42:03.000Z"
},
"created_at":{
"$date":"2020-10-09T12:01:59.000Z"
},
"projects":[
"5fa33513416100008d0070ba",
"5f80429814450000a6007c85",
"5f80436714450000a6007c86"
]
}
in my model i have created this method
public function push_user_projects($data, $where_data) {
return UserAccountsModel::where($where_data)->put($data);
}
The where_data works good. The method finds the correct documents to update.
But what doesent work is the pushing part. The following is what i put into data parameter
$data = array(
'projects' => array(
$projectData["_id"]
)
);
And when i se the result a complete new array has updated the projects field with the new value. But i want to append the value to the existing array. Can someopne help me?
To push another element into your data variable under 'projects'
$data['projects'][] = $projectData["_id"];

Using groupBy in Laravel resource

I want to pass a collection with a groupBy in laravel resource, But the problem is when i use that with collection method I can not modify the json and it throws a error:
PostResource:
public function toArray($request)
{
return [
'comments' => CommentResource::collection($this->comments->groupBy('star')),
];
}
Property [star] does not exist on this collection
But as soon as I remove the groupBy method from the collection it works. So how to get and modify the resource when it is grouped by with a specific key ?
"You could possibly group the collection once it has been created."
CommentResource::collection($this->comments)->collection->groupBy('star')
credits goes to devcircus with his answer on github
i use it and work successfully
CommentResource::collection($this->comments)->collection->groupBy('star')

Get sum of nested Collection failed Laravel Eloquent

I need the sum of nested relationship collection. When I try this code, the field could not be found.
return Offer::where("id", $offer_id)
->with(['rooms.products' => function($sql) use ($product_id) {
$sql->where('product_id', $product_id);
}]
)->sum("value");
Value field exists in rooms.products table.
Thanks in Advance
Right now, the sum() method will look for the value column in the offers table, while you need the value in the products table. Try this approach:
return Product::where('product_id', $product_id)
->whereHas('room.offer', function($sql) use ($offer_id) {
$sql->where("id", $offer_id)
})->sum("value");

Laravel Eloquent: how to add a column to a query response?

In other words, lets say i have a query like that:
return Location::valid()
->with('owners', 'gardeners')
->withCount('gardeners')
->get();
that returns some json :
[
{
name: 'LocationA',
nb_gardeners_max: 3,
owners: [...],
garderners: [...],
garderners_count: 2
}
]
in the json response i'd like to add some custom entry like is_full and available_places:
[
{
name: 'LocationA',
nb_gardeners_max: 3,
owners: [...],
garderners: [...],
garderners_count: 2,
...
is_full: false,
available_places: 1
}
]
I guess it has something to do with raw / join / aggregate... but i really don't understand how to do so. Any help will be greatly appreciated
EDIT
Minhajul answer is really usefull but it's not possible to do a WHERE clause on the appended attribute.
Location::where('is_full',true)->get() // NOT WORKING
Though it's still possible to do filter() on it, I'd like to use a JOIN for that to perform a single query
To do so, you can add attributes that do not have a corresponding column in your database.To do this, all you need to modify your model
public function getIsFullAttribute()
{
return $this->attributes['name'] == 'value';
}
After creating this accessor, you need to add this in your model.
protected $appends = ['is_full'];
Hopefully, it will help you.

Create collection from input array

Lets say I have a form that is a invoice. It has line items like $product[$key], $quantity[$key]. So when the form is submitted the input looks like
{
customer_id : "214"
product_id: [ "1","5", "6" ],
quantity: ["34", "1", "54"]
}
I have a model for that details table. What I have been doing is iterating over it and creating a details object then saving it like this
foreach($product as $key=>$p)
{
if($p)
{
$t = new Details;
$t->product = $p;
$t->quantity = $quantity[$key];
$t->save();
}
}
I'm guessing there is a way to be much more efficient about this. Like creating a collection of details straight from the input but I have no idea how I would accomplish that
You can instantiate models through mass assignment.
$details = new Details(['product_id'=>'1','quantity'=>'34']);
You can also specify columns of the table that you do not want to be mass assigned using the $guarded variable in the model.
Check out mass assignment in Laravel's docs: http://laravel.com/docs/eloquent#mass-assignment
For your particular issue it looks like you would need to build your input array out of the elements of the other arrays.
Seems it isn't possible. Here is Taylor responding to a issue request. It seems the problem is it wouldn't be possible to fire events then. I just ended up doing
$d = array();
foreach ($details as $detail) {
$d[] = new OrderDetail($detail);
}
$order->details()->saveMany($d);

Resources