Laravel- How to Remove a key from collection? - laravel

I have data as below:
[
{
"id": "3",
"title": "Boruto's Photo",
"is_lottery": 1,
"price": 10
},
{
"id": "4",
"title": "Misuki's Photo",
"is_lottery": 0,
"price": 20
}
]
I want to filter which is is_lottery == false remove the price key from this collection. The output is:
[
{
"id": "3",
"title": "Boruto's Photo",
"is_lottery": 1,
"price": 10
},
{
"id": "4",
"title": "Misuki's Photo",
"is_lottery": 0,
}
]

You can do this
$json = '[
{
"id": "3",
"title": "Boruto\'s Photo",
"is_lottery": 1,
"price": 10
},
{
"id": "3",
"title": "Misuki\'s Photo",
"is_lottery": 0,
"price": 20
}
]';
$filtered = collect(json_decode($json, true))->map(function ($array) {
if (!$array['is_lottery']) {
unset($array['price']);
}
return $array;
});
For native PHP you can do
$data = json_decode($json, true);
foreach ($data as $index => $array) {
if (!$array['is_lottery']) {
unset($array['price']);
}
$data[$index] = $array;
}

$json = [
{
"id": "3",
"title": "Boruto's Photo",
"is_lottery": 1,
"price": 10
},
{
"id": "4",
"title": "Misuki's Photo",
"is_lottery": 0,
"price": 20
}
];
$filtered = collect(json_decode($json))->map(function($value, $key) {
if (!$value['is_lottery']) {
Arr::except($value, 'price');
}
return $value;
});

you can declare new variable called $newCollection as final collection. Use foreach() to iterate your collection then delete the is_lottery from collection by using unset() then push it to $newCollection, this is example how you can delete it using foreach:
$newCollection = [];
foreach ($photos as $key => $value) {
if ($value["is_lottery"] == 0) {
unset($value["price"]);
}
array_push($newCollection,$value);
}
or you can try using forget to remove it from collection (not tested) from this ref:
How to unset (remove) a collection element after fetching it?

Related

Laravel 9 Rest API - pagination meta tag unavaible when return it with response()

Controllers/Komic Controller
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
return $result;
}
its fine when i directly return the $result
{
"data": [],
"links": {
"first": "http://localhost:8000/api/komik/a?page=1",
"last": "http://localhost:8000/api/komik/a?page=2",
"prev": null,
"next": "http://localhost:8000/api/komik/a?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 2,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=1",
"label": "1",
"active": true
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "2",
"active": false
},
{
"url": "http://localhost:8000/api/komik/a?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://localhost:8000/api/komik/a",
"per_page": 2,
"to": 2,
"total": 4
}
}
but when i'll return it using helpers/response
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2));
// send response
return response()->json($result, 200);
}
the meta and link on the json response will be disapppear and return result like this
{
"id": 1,
"title": "Spare me, Great Lord !"
},
{
"id": 2,
"title": "I'm An Evil God"
}
I want the response include the meta and link tags, how do i fix this?
If you want to meta data with response then you must need to add ->response()->getData(true) in collection results.
So your final function looks like :
public function search($value)
{
// Query Wildcards and Resources
$result = new KomikCollection(Komik::where('judul', 'like', '%'. $value .'%')->paginate(2))->response()->getData(true);
// send response
return response()->json($result, 200);
}

Laravel createMany error on nested relation

This is in relation to this question. I'm having this error:
TypeError
Illuminate\Database\Grammar::parameterize(): Argument #1 ($values) must be of type array, int given, called in /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php on line 920
While inserting data using createMany. This is the form request data:
{
"name": "My Order",
"orders": [
{
"date": "2022-05-17",
"product_id": [1],
"price": 1
},
{
"start_date": "2022-05-18",
"product_id": [2],
"price": 2
}
]
}
This is the store method:
$order = auth()->user()->orders()->create($request->validated());
$order_subs = $order->subOrders()->createMany($request->orders);
$order_sub_items = $request->only('orders')['orders'];
foreach ($order_subs as $key => $value) {
$value->subOrderProducts()->createMany([$order_sub_items[$key]);
}
However, if the product_id is not an array, it will store properly. Sample form request data:
{
"name": "My Order",
"orders": [
{
"date": "2022-05-17",
"product_id": 1,
"price": 1
},
{
"start_date": "2022-05-18",
"product_id": 2,
"price": 2
}
]
}
How to fix this error?

Laravel - Sort array by string value first and then date

I need help to sort array by couple of logics
[
{
"id": 1,
"status": "pending",
"date": "2019-08-01"
},
{
"id": 2,
"status": "delivered",
"date": "2019-08-01"
},
{
"id": 3,
"status": "pending",
"date": "2019-08-03"
},
{
"id": 4,
"status": "delivered",
"date": "2019-08-03"
},
{
"id": 5,
"status": "delivered",
"date": "2019-08-02"
}
]
what I want to do is to sort the array to status pending show first, and then sort it by the date descending
I already test to using sortByDesc from laravel collection but the array looks like sorted it by just 1 function
$collection = $collection->sortByDesc('date')->sortByDesc(function ($row, $key) {
if($row['status'] == 'pending'){
return 1;
}else{
return 0;
}
});
My expected final result look like this :
[
{
"id": 3,
"status": "pending",
"date": "2019-08-03"
},
{
"id": 1,
"status": "pending",
"date": "2019-08-01"
},
{
"id": 4,
"status": "delivered",
"date": "2019-08-03"
},
{
"id": 5,
"status": "delivered",
"date": "2019-08-02"
},
{
"id": 2,
"status": "delivered",
"date": "2019-08-01"
}
]
Few solutions:
Use a custom callback and return an array source
$products->sortBy(function($product) {
return [$product->param1, $product->param2];
});
This will sort a collection by param2 first, and then by param1
Use a custom callback and return a composite property to sort on source
$posts = $posts->sortBy(function($post) {
return sprintf('%-12s%s', $post->column1, $post->column2);
});
Sort your array by column 1, then split it up by column 2 and then merge it again (untested).
$collection->sortByDesc('date');
$collection->groupBy('status');
$collection->keyBy('status');
EDIT: Also I'm not sure if sortByDesc('date') works with date strings.
Your expected result can be achieved like this.
$sorted = $collection
->sortByDesc('date')
->sortBy(function ($item) {
return 'pending' == $item['status'] ? 0 : 1;
})
->values();
To be more precise:
$collection= $collection->sort(
function ($a, $b) {
if(($a->status== $b->status) &&($a->status== 'pending')){
return ($a->date >= $b->date) ? -1 : 1;
}elseif($a->status== 'pending' && ($a->status!= $b->status)){
return 1;
}else{
return ($a->date <= $b->date) ? 1 : -1;
}
}
);
$collection= $collection->sortByDesc('status');

Laravel foreach query builder result

I try to foreach a result then if name equal to "Apple "then i add a new row to next.
$list= Food::select('id', 'name')->get();
foreach ($list as $l) {
if($l->name == 'Apple'){
//Add 2 more item to next row
}
}
And my result output:
[
{
"id": 1,
"name": "Apple"
},
{
"id": 2,
"name": "Orange"
},
{
"id": 3,
"name": "Blueberry"
},
]
Here the result that i want to, for each to check if name is apple, then i need to add 2 more item manually.
[
{
"id": 1,
"name": "Apple"
},
{
"id": 1.1,
"name": "Apple Pie"
},
{
"id": 1.2,
"name": "Apple Juice"
},
{
"id": 2,
"name": "Orange"
},
{
"id": 3,
"name": "Blueberry"
},
]
For my own part, i use a temp array.
$list= Food::select('id', 'name')->get();
$tempList = array();
foreach ($list as $l) {
$tempList[] = $l;
if($l->name == 'Apple'){
$tempList[] = array('id' => 1.1, 'name' => 'Apple Pie');
}
}
But i think you can use Collection methods like "push"
Collections Push

How to join output of models in Laravel?

I have the following code:
$orders = OrderProduct::where(function ($query) use ($request) {
})->with('order_products')->orderBy('status', 'desc')->paginate(50)->toArray();
And order_products function is:
public function order_products()
{
return $this->hasMany("App\Order", "order_id", "order_id");
}
It gives me output result:
{
"user_id": "1",
"created_at": "2016-12-18 14:06:11",
"status": "2",
"note": "34535345",
"order_id": "2",
"address": "Kiev",
"courier_id": null,
"payment_type": "0",
"order_products": [
{
"id": 73,
"product_id": "1265",
"amount": "1"
},
{
"id": 74,
"product_id": "1266",
"amount": "1"
}
]
I need to join order_products with products_details, that to give title of product for each order like as:
"order_products": [
{
"id": 73,
"product_id": "1265",
"amount": "1",
"title": "Product name"
},
{
"id": 74,
"product_id": "1266",
"amount": "1",
"title": "Product name"
}
]
Instead this I get a new model output in response:
"products_details": [
{}, {}
]
How can I join two with models?
without joining, just using your first code:
in order_products, override the toArray() method.
function toArray() {
return [
id => $this->id,
product_id => $this->product_id,
amount => $this->amount,
title => $this->details->name
];
}
wich $this->details->name is the relation between order_products and products_details

Resources