Not getting multiple records result in foreach - php

I am trying to get each objects points and finally I need to add those points.
I am using foreach loop, but I get only one objects points as a result.
Please help me to get all objects points as sum
MODEL:
public function getTransactionPoint($transactionId)
{
$transaction = Transaction::find($transactionId);
$transactionCoupon = TCoupon::where('transaction_id', '=', $transactionId)->first();
$transactionPoint = TPoint::where('transaction_id', '=', $transactionId)->first();
$pointType = PointType::find($this->pointUser->point_type_id);
//to get transaction details
$trans_detail = DB::table('jocom_transaction_details AS a')
->select('a.*', 'b.*')
->leftJoin('jocom_products AS b', 'a.sku', '=', 'b.sku')
->where('a.transaction_id', '=', $transactionId)->get();
//for bpoints
if($pointType->type == 'BCard' )
{
foreach ($trans_detail as $value)
{
$date1=$value->valid_from;
$date2=$value->valid_to;
$startdate=strtotime($date1);
$enddate=strtotime($date2);
$in_range=false;
$out_of_range=false;
$nodate=false;
$today1= date("Y-m-d");
$today=strtotime($today1);
if(($today >= $startdate) && ($today <=$enddate))
{
$in_range=true;
}
else
{
$in_range=false;
$out_of_range=true;
}
if($in_range)
{
if($value->multibpoints)
{
$points = $value->multibpoints *$value->price;
}
elseif($value->bpoints)
{
$points = $value->bpoints;
}
}
if($out_of_range)
{
$points = ($value->price) * $pointType->earn_rate;
}
if ($points - floor($points) > 0.99) {
return floor($points) + 1;
} else {
return floor($points);
}
}//endforeach
}else
//for jpoints
foreach ($trans_detail as $key=>$value) {
$date3=$value->valid_from;
$date4=$value->valid_to;
$startdatee=strtotime($date3);
$enddatee=strtotime($date4);
$in_rangee=false;
$out_of_rangee=false;
$nodatee=false;
$today3= date("Y-m-d");
$today4=strtotime($today3);
if(($today4 >= $startdatee) && ($today4 <=$enddatee))
{
$in_rangee=true;
}
else
{
$in_rangee=false;
$out_of_rangee=true;
}
if($in_rangee)
{
if($value->multijpoints)
{
$points = $value->multijpoints * $value->price;
}
elseif ($value->jpoints) {
$points = $value->jpoints;
}
}
if($out_of_rangee)
{
$points = ($value->price) * $pointType->earn_rate;
}
if ($points - floor($points) > 0.99) {
return floor($points) + 1;
} else {
return floor($points);
}
}
}
}
}
Suppose product A has 22 jpoints and 33 bpoints and product b has 10 jpooints and 12 bpoints, I am getting only points of A product, but I need output as sum of product a and product b points
am trying to get each objects points and finally i need to add those points .am using foreach loop .but i am getting only one objects points as a result please help me to get all objects points as sum``

If I've understood your question correctly, the reason you're only getting the results for one product is because you're using return inside the loop. Instead, you can define a variable called something like $totalPoints, add to it and then return that value after the loop e.g.
$totalPoints = 0;
foreach ($trans_detail as $value) {
//The rest of the code
if ($points - floor($points) > 0.99) {
$totalPoints += floor($points) + 1;
} else {
$totalPoints += floor($points);
}
}
return $totalPoints;
Also, you don't have to use this but it would appear you can greatly simplify your code:
public function getTransactionPoint($transactionId)
{
$pointType = PointType::find($this->pointUser->point_type_id);
$trans_detail = DB::table('jocom_transaction_details AS a')
->select('a.*', 'b.*')
->leftJoin('jocom_products AS b', 'a.sku', '=', 'b.sku')
->where('a.transaction_id', '=', $transactionId)->get();
$pointsName = $pointType->type == 'BCard' ? 'bpoints' : 'jpoints';
$totalPoints = 0;
$today = strtotime(date('Y-m-d'));
foreach ($trans_detail as $value) {
if ($today >= strtotime($value->valid_from) && $today <= strtotime($value->valid_to)) {
$points = $value->multibpoints ? $value->multibpoints * $value->price : $value->$pointsName;
} else {
$points = ($value->price) * $pointType->earn_rate;
}
$totalPoints += $points - floor($points) > 0.99 ? floor($points) + 1 : floor($points);
}
return $totalPoints;
}

Related

What is the proper way to do for each where in laravel

I have these 2 functions below. I want to change $report->rate to count of results. So total rows from this query foreach($campaign->reports->where('status', 2) so if there is 10 results that's true it will be $total_cap = $total_cap + 10;
public static function checkTotalCap(Campaign $campaign)
{
$total_cap = 0;
foreach($campaign->reports->where('status', 2) as $report)
{
$total_cap = $total_cap + $report->rate;
}
if($campaign->cap <= $total_cap)
return true;
return false;
}
public static function checkDailyCap(Campaign $campaign)
{
$daily_cap = 0;
foreach($campaign->reports->where('status', 2) as $report)
{
if($report->created_at->isToday())
{
$daily_cap = $daily_cap + $report->rate;
}
}
if($campaign->daily_cap <= $daily_cap)
return true;
return false;
}
This is how its used
if($campaign->cap !== 0)
{
// Check if total cap or daily cap reached
if($this->checkTotalCap($campaign) || $this->checkDailyCap($campaign))
{
$campaign->active = 'no';
$campaign->save();
return "The campaign has reached its cap.";
}
}
You can do this pretty simply
$reports = $campaign->reports()->where('status', 2)->whereDate('created_at', now())->get();
foreach($reports as $report)
{
$daily_cap = $daily_cap + $report->rate;
}
Write separate query with conditions and simply loop it.
You can try this to filter the reports with status == 2 and:
$reports = $campaign->reports()->where('status', 2)->get();
foreach($reports as $report) {
//TODO
}
You don't even need the foreach() loops at all here:
public static function checkTotalCap(Campaign $campaign) {
return $campaign->reports()->where('status', 2)->count() > $campaign->cap;
// OR
// $campaign->cap <= return $campaign->reports()->where('status', 2)->count();
}
public static function checkDailyCap(Campaign $campaign) {
return $campaign->reports()->where('created_at', Carbon::today())->where('status', 2)->count() > $campaign->daily_cap;
// OR
// return $campaign->daily_cap <= $campaign->reports()->where('created_at', Carbon::today())->where('status', 2)->count();
}
Use SQL-level queries to get the SUM of each Report's rate column, and compare against $campaign->cap.

How can I subtract a value gotten from the loop

This is my code
// $res[] has two values(75000, 30000)
// $_SESSION['requestedAmt'] = 35000
while ($row = $queryWithdrawalTable->fetch_assoc()) {
$res[] = $row['profit_amt'];
foreach ($res as $amt) {
if ($_SESSION['requestedAmt'] > $amt) {
$calc = $_SESSION['requestedAmt'] - $amt;
} else {
$calc = $amt - $_SESSION['requestedAmt'];
}
}
echo $calc; // outputs 5000 40000
}
What I actually want to achieve is
$a[] = (1500, 3000);
$b = 2500;
while(fetch the data) {
$res = $a - $b;
}
// output = 2000
I want the value in $b to subtract the first value in $a(1500) and use result gotten from the first calculation to subtract from the second value(3000). please note I'm new to programming so any suggestion will be accepted thanks guys.
I want to be able to assign a single user to pay multiple users. for example user1 has to pay $100 to user2($25), user3($50) and user4($25). I have user1 money in $_SESSION['requestedAmt'] while the other users in $row['profit_amt']
You are almost there, you only perform the calculation after you have all the value inside the $res array
while ($row = $queryWithdrawalTable->fetch_assoc()) {
$res[] = $row['profit_amt'];
}
$calc = $_SESSION['requestedAmt'];
foreach ($res as $amt) {
if ($_SESSION['requestedAmt'] > $amt) {
$calc = $calc - $amt;
} else {
$calc = $amt - $calc;
}
}
echo $calc;
Or you don't need the $res array at all, perform the calculation while fetching the rows:
$cals = $_SESSION['requestedAmt'];
while ($row = $queryWithdrawalTable->fetch_assoc()) {
if ($_SESSION['requestedAmt'] > $row['profit_amt']) {
$calc = $calc - $amt;
} else {
$calc = $amt - $calc;
}
}

Recursive function to find the number of ways a number can be generated out of a set of numbers

I had a job interview test and the question I got was about making a function which would return the number of ways a number could be generated by using numbers from a certain set and any number in the set can be used N times.
It is like if I have the number 10 and I want to find out how many ways 10 can be generated using [2,3,5]
2+2+2+2+2 = 10
5+3+2 = 10
2+2+3+3 = 10
5+5 = 10
to solve it I made this function:
function getNumberOfWays($money, $coins) {
static $level = 0;
if (!$level) {
sort($coins);
}
if ($level && !$money) {
return 1;
} elseif (!$level && !$money) {
return 0;
}
if ($money === 1 && array_search(1, $coins) !== false) {
return 1;
} elseif ($money === 1 && array_search(1, $coins) === false) {
return 0;
}
$r = 0;
$tmpCoins = $coins;
foreach ($coins as $index => $coin) {
if (!$coin || $coin > $money) {
continue;
}
$tmpCoins[$index] = 0;
$tmpMoney = $money;
do {
$tmpMoney -= $coin;
if ($tmpMoney >= 0) {
$level++;
$r += getNumberOfWays($tmpMoney, $tmpCoins);
$level--;
} elseif (!$tmpMoney) {
$r++;
}
} while ($tmpMoney >= 0);
}
return $r;
}
This function works ok and returns the right value.
My question is if there is a better way for it.
Thanks

Trying to get property of non-object PHP Laravel

I know that this question in the tittle is asked WAYY too much in here, and I went thru most of them but still cant find a solution for my code.
function calculatingWages($project_id){
$start_date = '2017-05-01';
$end_date = '2017-12-31';
$project = Project::find($project_id);
$users = $project->users()->get();
$sumWage=0;
foreach ($users as $user){
$timesheetHours = $user->timesheets()->whereBetween('timesheets.date',[$start_date,$end_date])->sum('hours');
$wages = UserWage::whereBetween('start_date',[ $start_date,$end_date])->whereBetween('end_date',[ $start_date,$end_date])->get();
foreach ($wages as $wage){
$value = $wage->value;
$currency = $wage->currency;
$sumWage = extractMonthsAndCalculate($value,$currency, $timesheetHours, $start_date, $end_date);
}
return $sumWage;
}
}
function extractMonthsAndCalculate($value,$currency, $timesheetHours, $start_date, $end_date){
$start = Carbon::createFromFormat('Y-m-d',$start_date)->month;
$end = Carbon::createFromFormat('Y-m-d',$end_date)->month;
$diffOfMonths = $end - $start;
$sumWage = 0;
for ($i = $start; $i <= $diffOfMonths; $i++) {
$wageYear = Carbon::createFromFormat('Y-m-d',$start_date)->year;
$wageDay = Carbon::createFromDate($wageYear,$i,'01')->lastOfMonth()->toDateString();
$test = convertingALL($value,$currency,$timesheetHours,$wageDay);
}
return $sumWage;
}
function convertingALL($value, $currency, $timesheetHours, $date)
{
$currencyObj = Exchange::where('date',$date)->get()->first();
$currencyDate = $currencyObj->date;
$hourlyWage = 0;
$sumWage = 0;
if($currencyDate == $date) {
$dollar = $currencyObj->dollar_lek;
$euro = $currencyObj->euro_lek;
if ($currency == 'ALL') {
$sumWage = $value;
} elseif ($currency == 'USD') {
$sumWage = ($hourlyWage *$timesheetHours) * $dollar;
} else {
$sumWage = ($hourlyWage *$timesheetHours)* $euro;
}
}else{
$euro = 140;
$dollar = 136.4;
if ($currency == 'ALL') {
$sumWage = $value;
} elseif ($currency == 'USD') {
$sumWage = $value * $dollar;
} else {
$sumWage = $value * $euro;
}
}
return $sumWage;
}
it says that it cant get the property of a non object in line 468
this is line 467-468:
$currencyObj = Exchange::where('date',$date)->get()->first();
$currencyDate = $currencyObj->date;
when I dd $currencyDate it prints the date of it, tried to parse it using carbon but still same thing, where am I messing up?
You need to tell Eloquent that the date field contains a date (even though it seems obvious).
Docs: https://laravel.com/docs/5.4/eloquent-mutators#date-mutators
In your Exchange model you should have
class Exchange extends Model {
protected $dates = [ 'date' ];
On an unrelated note, ->get()->first() will pull every single result back from the database, then chuck all but one of them away. If you just call ->first() then you'll only get one result from the database; same end result but better for performance.

Foreach code working - but asking for optimalization

The below code works and does output exactly what i want. I made a foreach loop getting the values of a specific field ($CustomFields...) which is part of a framework variable. Then is only counts that field when the condition is "group".
After that i want to het the average price of all fields / count.
// ########### Get average hourly rate for group classes
$itemsperhour = array();
$countperhour = 0;
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson',$listing,false,false) == 'group') {
$itemsperhour[] = $CustomFields->field('jr_hourlyrateus',$listing,false,false);
$countperhour = $countperhour + 1;
}
}
//print_r($items);
if ($countperhour > 0) {
$totalperhour = array_sum($itemsperhour);
$averageperhour =($totalperhour / $countperhour);
echo round($averageperhour,2);
} else {
echo "No data";
}
unset ($averageperhour);
As said, the snippet works. But may I ask how other people would write such a script related to optimise such a piece of code (for speed and readability?
PHP 5.6+
Jasper
Below is one way of optimizing:
$totalperhour = 0;
$countperhour = 0;
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson',$listing,false,false) == 'group') {
$totalperhour += $CustomFields->field('jr_hourlyrateus',$listing,false,false);
$countperhour = $countperhour + 1;
}
}
if($countperhour > 0) {
$averageperhour =($totalperhour / $countperhour);
echo round($averageperhour,2);
$averageperhour = '';
} else {
echo "No data";
}
I would suppose to use array_reduce function for getting the average:
$averageperhour = array_reduce($listings, function($average, $listing) use (&$CustomFields)
{
static $sum = 0;
static $counter = 0;
if ($CustomFields->fieldValue('jr_typeoflesson', $listing, false, false) == 'group') {
$sum += $CustomFields->field('jr_hourlyrateus', $listing, false, false);
$counter ++;
$average = round(($sum / $counter), 2);
}
return $average;
}, 'No data');
echo $averageperhour;
Not sure about speed improvement (needs testing), but this variant seems to me like more readable.
How about this?
$itemsPerHour = [];
foreach($listings as $listing) {
if ($CustomFields->fieldValue('jr_typeoflesson', $listing, false, false) !== 'group') {
continue;
}
$itemsPerHour[] = $CustomFields->field('jr_hourlyrateus', $listing, false, false);
}
$countPerHour = count($itemsPerHour);
if ($countPerHour > 0) {
$averagePerHour = array_sum($itemsPerHour) / $countPerHour;
echo round($averagePerHour,2);
} else {
echo "No data";
}

Categories