laravel - trying to remove item from fetched collection - php

I need to remove items from a collection based on an attribute (Laravel 5.6).
$leagues = League::all();
foreach($leagues as $i => $L){
if($L->status == LeagueStatus::HIDDEN){
$leagues->forget($i); <<<<======== 1st attempt
unset($leagues[$i]); <<<<======== 2nd attempt
}
}
return response()->json($leagues->toArray());
Both methods removes the items correctly, but causes that response JSON comes as object:
{ <<<<======== ITS OBJECT WITH NUMBERED KEYS, NOT ARRAY
"0":{
"id":1,
"title":"test...
Correct JSON would be:
[ <<<<======== NORMAL ARRAY WITH OBJECTS
{
"id":1,
"title":"test...
Am I doing something wrong?

Use values to get a new Collection with the keys reset to consecutive integers:
return response()->json($leagues->values());
Laravel 6.x Docs - Collections - Available Methods - values

Just replace this
return response()->json($leagues->toArray());
to
return json_decode($leagues);

Related

How to combine multiple object in Laravel

I want to combine my ordered products and display the order list.
Controller :
$orders = Order::where('customer_id', 1)->pluck('products');
print_r($orders);
This is what I receive:
Array (
[0] =>
[
{"id":3,"product_id":3,"size":"47","quantity":7,"name":"Simple Regular T-shirt","price":2200,"thumbnail":"Thumbnail_614291597.jpg"},
{"id":7,"product_id":4,"size":"47","quantity":8,"name":"Simple Regular Shirt","price":123,"thumbnail":"Thumbnail_91520734.jpg"}
]
[1] =>
[
{"id":9,"product_id":3,"size":"45","quantity":2,"name":"Simple Regular T-shirt","price":2200,"thumbnail":"Thumbnail_614291597.jpg"}
]
)
But I want.
Array (
[0] =>
[
{"id":3,"product_id":3,"size":"47","quantity":7,"name":"Simple Regular T-shirt","price":2200,"thumbnail":"Thumbnail_614291597.jpg"},
{"id":7,"product_id":4,"size":"47","quantity":8,"name":"Simple Regular Shirt","price":123,"thumbnail":"Thumbnail_91520734.jpg"},
{"id":9,"product_id":3,"size":"45","quantity":2,"name":"Simple Regular T-shirt","price":2200,"thumbnail":"Thumbnail_614291597.jpg"}
]
)
How I can do this?
I already tried a different way, but I can't do this. Firstly I was trying to convert it array and then use the array_marge() function for those arrays. but that array needs only two arrays but for my case, it is not specified how many arrays the user has given. And try to solve it with a loop (I just tried). I am new in this field.
You could try
$orders = Order::where('customer_id', 1)
->pluck('products')
->values()
->flatten(1);
The pluck will return a collection, flatten with a depth of 1 will remove the nesting. values will reset the keys to sequential - (it's not strictly necessary here)
Laravel Docs - Collections - Values
Laravel Docs - Collections - Flatten
Just add flatten() after applying the query (with ->get()):
$orders = Order::where('customer_id', 1)->get()->pluck('products')->flatten();
print_r($orders);
Side note:
Instead of print_r() You can use dump() to pretty print the output in your browser
$orders->dump(); //only dump
$orders->dd(); //dump and exit

Extract particular array from multidimensional array

I have a JSON array of data that I am trying to extract particular value/keys(?) from, and would like to add them into a new array.
The array looks like this:
{ "total':2000,
"achievements":[
{
"id":6,
"achievement":{},
"criteria":{
"id":2050,
"is_completed":false
},
"completed_timestamp":1224053510000
},
{
"id":8,
"achievement":{},
"criteria":{
"id":1289,
"is_completed":true
},
"completed_timestamp":0000000
}
]
}
I want to search for true in the is_completed, and then add the id from that array into a new array.
Basically, find the id's of all the key/array (sorry unsure of terminology) where is_completed is true.
I've tried something simple like finding trying to find the key of an ID, but struggling to get that to work. And also seen some of the multi-level for loop examples but can't get them to work for my data.
Example:
$key = array_search('1289', array_column($array, 'id'));
As pointed out in the comments, you could combine array_filter (to filter completed events) and array_column (to extract their IDs).
$completedAchievements = array_filter(
$array->achievements,
static function (\stdClass $achievement): bool {
return $achievement->criteria->is_completed === true;
}
);
$completedAchievementsIds = array_column($completedAchievements, 'id');
print_r($completedAchievementsIds); // Array([0] => 8)
Note: the code above supposes your JSON was decoded as an object. If it was decoded as an array, just replace -> syntax with the corresponding array index access.
Demo

Modify JSON Feed With php

I have a JSON Feed which is accessed by an api.
The json feed it returns is as below:
[
{
"isoDate":"2017-09-15T00:00:00.0000000",
"events":[
{
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
},
{
"isoDate":"2017-09-16T00:00:00.0000000",
"events":[
{
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
}
]
I need the isoDate to be listed with each event instead of individually.
e.g.
[
{
"events":[
{
"isoDate":"2017-09-15T00:00:00.0000000",
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"isoDate":"2017-09-15T00:00:00.0000000",
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
},
{
"events":[
{
"isoDate":"2017-09-16T00:00:00.0000000",
"id":"-7317",
"name":"Exhibition SKMU: The collection 2015-2017",
},
{
"isoDate":"2017-09-16T00:00:00.0000000",
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
]
}
]
Can this be achieved with php? Basically fetch that feed from a url and then display it in my preferred format?
So this is what you have to do, to get back your desired format of the json,
$json is your json string:
$eventList = json_decode($json);
foreach($eventList as $eventEntry){
$isoDate = $eventEntry->isoDate;
foreach($eventEntry->events as $subEventEntry){
$subEventEntry->isoDate = $isoDate;
}
//delete the isoDate from outer
unset($eventEntry->isoDate);
}
echo json_encode($eventList);
So basically, you are first decoding your json into php structure, apply your changes and after that, encode it back. Note here, that I have not appened true as second parameter for the $json_decode, but working with the resulting object.
Also: Your json is not standard comform and could result in errors. PHP will properly not decode it, because your object end with a comma. The last element of an object should be without comma. Instead of
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo",
}
make it like this:
{
"id":"-91417",
"name":"Torget - a multi cultural meeting place in Geilo"
}
I know, this can be a problem, when you get it from an API, but this is another problem of itself...
EDIT:
To get every "events" into one big array, you have to store them just like your imagination ;) . Think it like this: $subEventEntry holds one "events"-object. Because you are iterating both levels, you see everyone object of them. My suggestion would be to store them in a new array, and recreating the structure around it:
$everything = new stdClass();
$everything->events = array();
and then, in the inner loop:
foreach($eventList as $eventEntry){
$isoDate = $eventEntry->isoDate;
foreach($eventEntry->events as $subEventEntry){
$subEventEntry->isoDate = $isoDate;
$everything->events[] = $subEventEntry; // <-- this has to be added
}
//delete the isoDate from outer
unset($eventEntry->isoDate);
}
When recreating the structure, and you don't need the old structure anymore you could remove the unset.
Just remeber every [ ] pair in the json represents an array, every { } pair an object (stdClass). The name of this object/array is referenced -> by its class property in the superobject.
Yes you can using json_decode() function for example:
$yourjson;/* your json */
$events = json_decode($yourjson, true);
foreach($events as $event){
echo $event["isoDate"];
}
You can use json_decode to decode the json object to php array then modify the array and encode it using json_encode

Extract elements from stdClass in PHP dynamically

I have stdClass returned from Laravel ORM result which looks like below,
I know I can access the value using $object->Tables_in_questip3_qgen, but "Tables_in_questip3_qgen" is dynamic. This can change to any string and I would like to extract values only from first element. I would like to have only adj_table,admin_fi and admin_fi_acount values across rows.
In Laravel 5+ you can do this:
collect($object)->map(function ($v) {
return head((array)$v);
});
To get a subarray of arbitrary items (by the order they appear):
$indices = [ 0, 1 ];
collect($object)->map(function ($v) use ($indices) {
$inner = collect($v)->values();
return $inner->only($indices); //This will return the requested indices as a collection, but you can realistically do whatever you want with them like e.g. ->implode or ->toArray
});

How to access the nth object in a Laravel collection object?

I have a laravel collection object.
I want to use the nth model within it.
How do I access it?
Edit:
I cannot find a suitable method in the laravel documentation. I could iterate the collection in a foreach loop and break when the nth item is found:
foreach($collection as $key => $object)
{
if($key == $nth) {break;}
}
// $object is now the nth one
But this seems messy.
A cleaner way would be to perform the above loop once and create a simple array containing all the objects in the collection. But this seems like unnecessary duplication.
In the laravel collection class documentation, there is a fetch method but I think this fetches an object from the collection matching a primary key, rather than the nth one in the collection.
Seeing as Illuminate\Support\Collection implements ArrayAccess, you should be able to simply use square-bracket notation, ie
$collection[$nth]
This calls offsetGet internally which you can also use
$collection->offsetGet($nth)
and finally, you can use the get method which allows for an optional default value
$collection->get($nth)
// or
$collection->get($nth, 'some default value')
#Phil's answer doesn't quite obtain the nth element, since the keys may be unordered. If you've got an eloquent collection from a db query it'll work fine, but if your keys aren't sequential then you'll need to do something different.
$collection = collect([0 => 'bish', 2 => 'bash']); $collection[1] // Undefined index
Instead we can do $collection->values()[1] // string(4) bash
which uses array_values()
Or even make a macro to do this:
Collection::macro('nthElement', function($offset, $default = null) {
return $this->values()->get($offset, $default);
}):
Example macro usage:
$collection = collect([0 => 'bish', 2 => 'bash']);
$collection->nthElement(1) // string(4) 'bash'
$collection->nthElement(3) // undefined index
$collection->nthElement(3, 'bosh') // string (4) bosh
I am late to this question, but I thought this might be a useful solution for someone.
Collections have the slice method with the following parameters:
$items->slice(whereToStartSlice, sizeOfSlice);
Therefore, if you set the whereToStartSlice parameter at the nth item and the sizeOfSlice to 1 you retrieve the nth item.
Example:
$nthItem = $items->slice($nth,1);
If you are having problems with the collection keeping the indices after sorting... you can make a new collection out of the values of that collection and try accessing the newly indexed collection like you would expect:
e.g. Get the second highest priced item in a collection
$items = collect(
[
"1" => ["name" => "baseball", "price" => 5],
"2" => ["name"=> "bat", "price" => 15],
"3" => ["name" => "glove", "price" => 10]
]
);
collect($items->sortByDesc("price")->values())[1]["name"];
// Result: glove
Similar to morphs answer but not the same. Simply using values() after a sort will not give you the expected results because the indices remain coupled to each item.
Credit to #howtomakeaturn for this solution on the Laravel Github:
https://github.com/laravel/framework/issues/1335

Categories