PHP array_map() always change my first index value to zero value - laravel

I have a controller in Laravel
This is my collection
$milestones = $this->getmilestones();
dump($milestones);
and the value is
array:3 [▼
0 => "["109"
1 => "110"
2 => "111"]"
]
And I tried this code based on the answer here.
So, I have code like this
array_unshift($milestones, $milestones[0]);
unset($milestones[0]);
dump($milestones);
and the value is (index was changed)
array:3 [▼
1 => "["109"
2 => "110"
3 => "111"]"
]
So, after unshifting the collections, I tried to use array_map to convert array of strings to array of integers.
$milestones = array_map('intval', $milestones);
dump($milestones);
But, I still got the same value. The first index returns 0 like this
array:3 [▼
1 => 0
2 => 110
3 => 111
]
What should I do?

Try this one
array_splice($milestone, 0, 1);
dump($milestone);

Ah, finally I got the results that I wanted. I try to remove square brackets and double quote. Because milestones is collection. So my code is
$milestones = str_replace(array('[', ']', '"'),'',$milestones);
Thank you all for your help

Use array_values this should re-index your array the way you need it:
$milestones = array_values($milestones);
If $milestones is a collection:
$milestones = $milestones->values();
The method values() will call array_values on your items defined in your collection instance.
Source: http://php.net/manual/en/function.array-values.php

Related

Need to Get data of ID ( received in Array ) from database

Good Morning. I am trying to get the data for each BuffaloID which i get in array. From that ID i am trying to get milk record for each buffaloID. But 2nd query give the data for first id only. How can i get the data for each id.
Query
$buffalidforavgmilk = Buffalomilkrecord::groupBy('buffaloID')->get('buffaloID')
->pluck('buffaloID')->toArray();
array:4 [▼
0 => "Buffalo-01"
1 => "Buffalo-02"
2 => "Buffalo-03"
3 => "Buffalo-04"
]
When i try below query i received data only for first id
$avgbuffalomilk = Buffalomilkrecord::where('buffaloID',$buffalidforavgmilk)->
pluck('totalmilk')->toArray();
array:5 [▼
0 => "9.00"
1 => "13.00"
2 => "12.00"
3 => "13.00"
4 => "12.00"
]
I hope i describe my problem and where did i make mistake to get data for all ID
Thanks in Advance
use whereIn
$buffalidforavgmilk = ['1','2','3'];
$avgbuffalomilk = Buffalomilkrecord::whereIn('buffaloID',$buffalidforavgmilk)->pluck('totalmilk')->toArray();

Laravel Query with Sum of value from child table if value column in parent table greater than sum of value in child

I am trying to query for rows from transaction table where the amount is less than sum of allocations against that transaction row in allocations table. This works halfway. It is giving me all transaction queries with an additional field of "allocated_amount".
$all_transactions = Transaction::
withCount([
'allocations AS amount_allocated' => function ($query) {
$query->select(
DB::raw("CAST(SUM(amount) AS INTEGER)"
));
}
])
->where('contact_type','supplier')
->where('contact_id',$ehead->supplier_id)
->get()->toArray();
Result
0 => array:12 [▼
"id" => 4
"amount" => 10000
"created_by" => 1
"amount_allocated" => 7500
]
1 => array:12 [▼
"id" => 5
"amount" => 10000
"created_by" => 1
"amount_allocated" => 10000
]
But I don't want the second result to come up because amount = amount allocated. How to fix this query?
Tried using:
->where('amount','>','allocated_amount')
but maybe because it is additionally added filed, throws an error saying allocated field does not exist. I need it within the query, not as a separate addition.
Well, in this case you can simply use map()
$all_transactions = collect($all_transactions)->map(function ($row) {
if ($row['amount'] > $row['amount_allocated']) {
return $row;
}
})->filter()->toArray(); // filter() to remove null values

Group the result of an already grouped query sql/laravel

Hello everyone this is my first post and after giving this a lot of work my head just doesn't want to cooperate anymore, I've searched online for answers but can't find related cases, I am working in laravel 5.2 with a query, said query is to get the progress on items and count the items that share the same progress to display in a pie chart.
Relations are as follows:
I have 3 tables:
Items
Steps to complete (each one has a percentage).
Progress of each item per step (Completed true or false)
Right now I have this code
table('items as i')
->join('items_sectors as is', 'i.sector_id', '=', 'is.id')
->join('sectors_steps_progress as stp', 'i.id', '=', 'stp.item_id')
->join('sectors_steps as cs', 'stp.step_id', '=', 'cs.id')
->where('stp.completed', true)
->selectRaw('count(distinct i.id) as count, CONCAT(sum(cs.percentage), "%") as percentage')
->groupBy('stp.completed', 'i.id');
And this with some testing data outputs
array:3 [▼
0 => {#2042 ▼
+"count": 1
+"percentage": "50%"
}
1 => {#2043 ▼
+"count": 1
+"percentage": "100%"
}
2 => {#2044 ▼
+"count": 1
+"percentage": "100%"
}
]
What I want is to now join all the matchings "percentage" and count them so it would end up like:
array:3 [▼
0 => {#2042 ▼
+"count": 1
+"label": "50%"
}
1 => {#2043 ▼
+"count": 2
+"label": "100%"
}
]
Thanks a lot if anyone can help me with this, I'm still trying to figure it out :(
if result is not a collection convert it to a collection and apply the code below
$result = $array->groupBy("percentage")
->map(function($q){
$newArray['count'] = count($q);
$newArray['percentage'] = $q[0]['percentage'];
return $newArray;
})->values();
return $result;
Hope it helps.

How to get an array of 2-tuples from Laravel query builder?

Basically, I want to do this:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->map(function($c) { return [$c->id, $c->name]; })->toArray();
But without such a verbose map function. Isn't there a get-like method that will return flat numeric arrays instead of objects?
To be clear, the output should look like this:
array:4 [
0 => array:2 [
0 => 4
1 => "My Company"
]
1 => array:2 [
0 => 14
1 => "Example Company"
]
2 => array:2 [
0 => 13
1 => "Best Company"
]
3 => array:2 [
0 => 12
1 => "Super Co"
]
]
This is what I mean by 2-tuples: two-element numeric arrays. I know they don't exist in PHP, but the concept is the same; each entry has a fixed length.
There is no function out of the box to do this, but Laravel's Collection is Macroable, so you can add your own function to it to do this.
For example, somewhere in your code (like the boot() method of your AppServiceProvider), you can add a new method to the Collection:
// add toIndexedArray method to collections
\Illuminate\Support\Collection::macro('toIndexedArray', function() {
return array_map('array_values', $this->toArray());
});
Now you can use this new method like any other normal Collection method, so your final code would be:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->toIndexedArray();
If this is something you need a lot, you can change the PDO fetch mode in config/database.php to PDO::FETCH_NUM. I'm assuming it's possible to change it on-the-fly as well, but the code probably won't look that great. I don't think there's a Laravel command to change it for a single query, I'm afraid.
Otherwise, since the array is multidimensional, I'm afraid you do need to map over them somehow, and Laravel collections don't work nicely with e.g. ->map('array_values') which would have been a lot cleaner.
You could wrap it in array_map('array_values', $array) but that seems silly.
At least you could make it a little shorter if you change ->map() to ->transform() - then you don't need to tack on the ->toArray() at the end.
Use pluck():
$locals['companies'] = Company::orderBy('name')->pluck('id', 'name')->toArray();
If you need a list for Form::select this will work:
$locals['companies'] = Company::orderBy('name')->pluck('name', 'id');
You can omit the map function and just do:
$locals['companies'] = Company::orderBy('name')->get(['id','name'])->toArray();

get the first, the second, the third element of collection

I have a collection like that:
Collection {#750 ▼
#items: array:18 [▼
18 => User {#691 ▶}
19 => User {#696 ▶}
20 => User {#701 ▶}
]
}
Where 18, 19, 20 should vary
I tried to call with
$collection->get(0);
$collection->get(1);
$collection->get(2);
But obviously, it doesn't work
I found a workaround with shift, that return first element and remove it from the collection,
$el1 = $collection->shift();
$el2 = $collection->shift();
$el3 = $collection->shift();
But in this case, my original collection is destroyed.
Any idea how I should do it?
You can use slice() method:
$collection->slice(0, 3)
The slice method returns a slice of the collection starting at the given index. If you would like to limit the size of the returned slice, pass the desired size as the second argument.
You can use values() as:
$collection = $collection->values();
then you can use it as:
$collection->get(0);
$collection->get(1);
$collection->get(2);
You can either loop over them:
foreach ($collection as $element) {
// use $element
}
Or you can reset the keys to be sequentially indexed:
$collection = $collection->values();
$element1 = $collection->get(0);
$element2 = $collection->get(1);
$element3 = $collection->get(2);
There are many ways you can access thoes values. For example, you can get keys by calling:
$keys = $collection->keys()
Then call by the ordered keys you wanted:
if (isset($keys[0])) $collection->get($keys[0]);

Resources