php - how to add all the numbers in an array - php

[
{
"total": 71
},
{
"total": 66
}
]
How can i sum both numbers up to give me = 137. I have tried array_sum($array_result) but the spits and error saying :
array_sum() expects parameter 1 to be array, object given
this is my code
$result = DB::table('marks')->where([
['term', $request->term],
['subject', $request->subject],
['class', $student->class],
['arm', $student->arm],
])->select('total')->get();
return array_sum($result);
return redirect()->back()->with('success', 'Results marked successfully.');

If you just need to sum up total, use sum() Query Builder method:
$result = DB::table('marks')->where([
['term', $request->term],
['subject', $request->subject],
['class', $student->class],
['arm', $student->arm],
])->sum('total');

Easiest to put them in a collection and call sum() method.
Like that:
$sum = collect($yourArray)->sum('total');
You could do it with foreach and a temporary variable as well though.

$result = DB::table('marks')->where([
['term', $request->term],
['subject', $request->subject],
['class', $student->class],
['arm', $student->arm],
])->select('total')->get();
$result = $result->toArray();
Now you can simply do this as mentioned by devk
collect($result)->sum('total');
get() return collection. you directly perform actions on collections
like get()->sum('total')
I hope this helps.

Related

Querying sum of multiple aggregate columns (without groupBy)

I have a transactions table and I'm trying to get the total of each type.
To simply put it looks like this
id
type
credit_movement
1
top_up
10000
2
fee
-50
3
deduct
-1000
I am trying to get sum of each type to show as a report.
top_up: 10000
fee: 50
deduct: 1000
net_expense: 9850 [top_up - deduct - fee]
$types = [
'top_up' => ['top_up'],
'deduct' => ['deduct'],
'fee' => ['fee'],
'net_expense' => ['top_up', 'deduct', 'fee'],
];
$query = DB::table('transactions');
foreach ($types as $type => $fields) {
$query->selectSub(function ($query) use ($fields) {
return $query->selectRaw('SUM(credit_movement)')->whereIn('type', $fields);
}, $type);
};
$results = $query->get();
When I do this, I get:
1140 In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'project.transactions.type'; this is incompatible with sql_mode=only_full_group_by..
When I change my database.mysql.strict = false, it works; however I want to make it work properly without needing to change the mysql config.
As of my understanding, this error indicates that I am only selecting aggregated columns, but in my case I don't actually want to groupBy() anything as this is just reports.
If I try to groupBy('type') it returns everything grouped by type, but the queries are only run within that group.
{
0: {
top_up: 10000,
deduct: 0,
fee: 0,
net_expense: 10000
}
1: {
top_up: 0,
deduct: -1000,
fee: 0,
net_expense: -1000
},
// etc...
}
Is there a way to obtain without changing strict to false?
{
0 => {
top_up: 10000,
deduct: -1000,
fee: -50,
net_expense: 9850
}
}
If I understand you correctly this might be very easy but again I might have not understood it right.
$result = DB::table('transactions')->selectRaw('type, SUM(credit_movement) as sum')->groupBy('status')->get();
This should return something like this:
type
sum
fee
-5656
topup
8758
deduct
-7625
For the total sum you can just do it in php which would make it easier
$net = $result->sum('sum'); // equals -5656+8758-7625
Hope this helps and let me know if I am wrong about it.
The problem with your approach is in the final column that is the sum of the other 3 so you can't use SUM because you don't have a column to group.
You could use a subquery but I think that the best solution is to add a little elaboration of the raw data that you get from a simpler query.
$query = DB::table('transactions')
->selectRaw('type, SUM(credit_movement) AS movements')
->groupBy('type');
$results = array_reduce($query->get(), function(array $res, array $value){
$res[$array['type']] = $array['movements'];
return $res;
}, []);
$results['net_expense'] = array_sum($results);

How to sort array with condition using loop in php

I am working with codeigniter and i want to fetch recods as "two arrays"
based on condition (FilterType='Tag',FilterType='Merchant')
Here is my table "filterproducts"
id FilterType CategoryUrl
1 Tag abc
2 Tag xyz
3 Merchant abc
4 Merchant abc
Here is my current code which is giving me multidimenional array
function SearctRecords()
{
$this->db->select("*")
->from("filterproducts fp")
->join("filterid fi", "fp.FilterType=fi.name")
->where("fp.CategoryUrl", $CategoryUrl);
$query = $this->db->get();
$result = $query->result_array();
return $result;
}
Here is my controller
function SearchFilterProducts()
{
$users['data'] = $this->Customer_model->SearctRecords($CategoryUrl);
$responseJSON = array("Status" => $status, "data" => $users['data']);
header("content-type:application/json");
$response = json_encode($responseJSON);
echo $response;
}
I would recommend to sort using existing DB sorting methods. Usually will perform better than custom PHP function.
I you still want to sort your multidimensional result, consider using usort.
function custom_super_comparator($a, $b) {
//custom comparison
}
usort($response, "custom_super_comparator");
Check this good answer on this topic:
Sort array of objects by object fields
offtopic, SearctRecords is missing the argument
SearctRecords($CategoryUrl) {

Doctrine ORM serialization after join

I guys I am working diwth doctrine JOINS and I came across a problem.
I have done a query with joins and it seems ok, the results are good! but the output is terrible
public function getMarketcapData($page = -1, $limit = -1){
$pageAndCount = $page>-1 && $limit>0;
$qb = $this->getEntityManager()->createQueryBuilder();
$q = $qb->select('cc, count(cr) as coinRawsCount, cmc as relatedCategory')
->from('AppBundle:CoinClean', 'cc')
->leftJoin("AppBundle:CoinRaw", "cr", 'WITH', 'cc = cr.coinClean')
->leftJoin("AppBundle:CoinMapCategory", "cmc", 'WITH', 'cc.relatedCategory = cmc')
->andWhere('cc = cr.coinClean')
->andWhere('cc.relatedCategory = cmc')
->groupBy('cc.id')
;
if($pageAndCount) $q = $q->setFirstResult($page*$limit)->setMaxResults($limit);
$q= $q->orderBy('cc.rank', "ASC")->getQuery();
$result = $q->getResult();
if($pageAndCount){
$qb = $this->getEntityManager()->createQueryBuilder();
$q = $qb->select('count(u.id)')->from('AppBundle:CoinClean', 'u')->getQuery();
return new PageResult($result, (int)$q->getSingleScalarResult(), $page, $limit );
}else{
return $result;
}
}
here you have the output: it is an array made by array + obejcts
data:[
[ // first query result
{data from cc} // ony one object
],
{// first query result from join
"coinRawsCount": 4,
"relatedCategory": {...}
},
[ // second query result
{data from cc2} // ony one object
],
{// second query result from join
"coinRawsCount": 4,
"relatedCategory": {...}
}
]
my goal is to condense all in
"data":[
{
"data": {...},
"coinRawsCount": 4,
"relatedCategory": {...}
},
{
"data": {...},
"coinRawsCount": 4,
"relatedCategory": {...}
},
]
Any ideas?
You could loop over the result and merge on every other row, e.g. like this:
$rows = $q->getResult();
$result = []
foreach ($rows as $index => $row) {
if ($row instanceof App\Entity\CoinClean) {
// Skip first row and merge data when reading next row
continue;
}
$result[] = array_merge(
['data' => $rows[$index - 1]],
$row
);
}
return $result;
Assuming the first row is always the entity, we will skip this entry using continue;. The next row should contain an array with the additional data. We can then take the previous offset ($index - 1) to fetch the entry and the current row and merge them together. You might have to do additional checks.
Keep in mind that you will loop over a potentially large array and since you copy the data over to a new array this might use up a considerable amount of memory. So you might have to profile and optimize it, if you notice poor performance.
Other options would be to perform a native SQL query and then just map the output using a ResultSetMappingBuilder or to use custom hydration, i.e. create a new custom DTO-object for that query, that better fits the resulting data than the original entity structure, using DQL SELECT NEW App\Dto\MyModel FROM ...your query...'.

Cannot use object of type stdClass as array when looping with array

I'm trying to get Count of a table called TestRunList that has the foreign key the same as another table called Testrun meaning i want to get count of how many testrunlist that single testrun has in the same page i did a forloop to get testrun id for each testrunlist but it didn't seem to work i get this error
Cannot use object of type stdClass as array
heres my Code in the controller
$data = DB::table('TestRun')->get();
$runs=array();
for ($i=0;$i<sizeof($data);$i++)
{
$testrunID=$data[$i]['TestRunID'];
$Testrunlist=TestRunList::where('test_run_id',$testrunID)->count();
$runs[$i]=[
'Countruns'=>$Testrunlist
];
}
return view('management.testrun.testrun-list')
->with('data',$data)
->with('runs', $runs);
$data is a Collection, you can't access using array syntax
$data = DB::table('TestRun')->get();
$runs = [];
$data->each(function ($row) use ($runs) {
$runs[] = [
'Countruns' => TestRunList::where('test_run_id',$row-> TestRunID)->count()
];
});
return view('management.testrun.testrun-list')
->with('data',$data)
->with('runs', $runs);
Always use
print_r($data);
if it's object run echo $data->username if array run echo $data['username'];
So you know what type of data you're dealing with.

Laravel Eloquent Pluck without losing the key

I have the following collection in Laravel:
["TheNumbers":[{"episodeID":16818,"episodeNumber":100,"created_at":null,"updated_at":null},{"episodeID":16818,"episodeNumber":210,"created_at":"2017-02-20 21:30:38","updated_at":"2017-02-20 21:30:38"}]
If I run the following code:
$TheEpisode->TheNumbers->pluck('episodeNumber');
I will get the following result:
[100,210]
I would like to keep the keys for each number, how can I achieve this?
EDIT: EXPECTED RESULT:
This is my expected result:
[{"episodeNumber":100},{"episodeNumber":210}]
PHILIS PETERS (improved)
TheEpisode->TheNumbers->reduce(function ($result, $episode) {
$episodeData = (collect())->put('episodeNumber', $episode['episodeNumber']);
$result[] = $episodeData;
return $result;
}));
Pluck() can take two params. The second of which is what the value can be keyed by.
You should be able to do:
$TheEpisode->TheNumbers->pluck('episodeNumber', 'episodeID');
Hope this helps!
Try something like this, it should work using map...
return $TheEpisode->TheNumbers->map(function ($episode) {
return ['episodeNumber' => $episode['episodeNumber']];
});
This can be simply achieved by passing a second argument to pluck. From the documentation:
You may also specify how you wish the resulting collection to be
keyed:
$plucked = $collection->pluck('name', 'product_id');
$plucked->all();
// ['prod-100' => 'Desk', 'prod-200' => 'Chair']
$collection->forget(['created_at', 'updated_at]);
This will simply left two first key-value pairs. Worth to keep in mind:
forget does not return a new modified collection; it modifies the collection it is called on.
Laravel docs
This should work properly:
$collection->only(['episodeID', 'episodeNumber']);
Try using
$TheEpisode->TheNumbers->lists('episodeNumber');
the key will remain.
Try using mapWithKeys like this:
$TheEpisode->TheNumbers->mapWithKeys(function ($theNumber) {
return ['episodeNumber' => $theNumber['episodeNumber']
});
I assume you want the result like this:
"TheNumbers":['episodeNumber':100,'episodeNumber':210]
For sake of updated Laravel, I tried all and I found
return Model::get(['name','id'])
will give reduced results with key => value.

Categories