PHP - join equal arrays and add count of arrays joined - php

I have a task on my Laravel project that runs every day and check for expiration on some coupons. If they expire that day, I add them as array to the user table to display them on the admin panel. Problem is, client wants them to be shown joined if they share date and price properties and I'm having some trouble finding the appropriate way to do this. Let me explain:
$coupons = Coupon::where([['date_end', date('Y-m-d')], ['status', '!=', 0]])->get();
foreach ($coupons as $key => $coupon)
{
$user = User::where('id', $coupon->user_id)->first();
$coupon->status = Coupon::EXPIRED;
$coupon->save();
if ($user->expired_coupons == NULL)
{
$coupons_expired = [];
}
else
{
$coupons_expired = json_decode($user->expired_coupons);
}
$last_coupon_expired['date'] = $coupon->date_end;
$last_coupon_expired['quantity'] = 1;
$last_coupon_expired['price'] = $coupon->voucher->available->price_per_meal;
$coupons_expired[] = $last_coupon_expired;
$user->expired_coupons = $coupons_expired;
$user->save();
}
And I'll get something like this in the db:
[{
"date": "2020-05-24",
"quantity": 1,
"price": 5
}, {
"date": "2020-05-24",
"quantity": 1,
"price": 5
}, {
"date": "2020-05-24",
"quantity": 1,
"price": 10
}, {
"date": "2020-05-23",
"quantity": 1,
"price": 5
}]
Which looks like this in my admin panel:
And in this case, the way I'd want it to show would be:
- 2020-05-24 || 2 || 5
- 2020-05-24 || 1 || 10
- 2020-05-23 || 1 || 5
If I didn't need the quantity I could just get rid of the arrays that are exactly equal, but everything I tried to get the thing working as I want to has failed. Any pointers? Thanks.

If it is possible to share the data what you have got $coupons variable. But i tried to solve the problem by grouping the date and price. May be there need to more improvement.
$coupons = Coupon::where([['date_end', date('Y-m-d')], ['status', '!=', 0]])->get();
$coupons_expired = [];
foreach ($coupons as $key => $coupon)
{
$user = User::where('id', $coupon->user_id)->first();
$coupon->status = Coupon::EXPIRED;
$coupon->save();
if ($user->expired_coupons == NULL)
{
$coupons_expired = [];
}
else
{
$coupons_expired = json_decode($user->expired_coupons);
}
if (isset($coupons_expired[$coupon->date_end][$coupon->voucher->available->price_per_meal])) {
$coupons_expired[$coupon->date_end][$coupon->voucher->available->price_per_meal]['quantity']++;
} else {
$coupons_expired[$coupon->date_end][] = [
$coupon->voucher->available->price_per_meal => [
'data' => $coupon->date_end,
'quantity' => 1,
'price' => $coupon->voucher->available->price_per_meal
]
];
}
$user->expired_coupons = $coupons_expired;
$user->save();
}
$mappedData = [];
foreach ($coupons_expired as $data => $dateGroups) {
foreach ($dateGroups as $qty => $coupon) {
$mappedData[] = $coupon;
}
}

I came up with this solution that, for now, meets my needs. Since the date will always be the same for the coupons that expire (being a daily task) I just create an array with all the prices and the amount of times they appear, and then iterate it to make the final array of coupons expired joined by date and price.
foreach ($coupons as $key => $coupon)
{
$coupon->status = Coupon::EXPIRED;
$coupon->save();
$expired_coupon_price['price'] = (string)$coupon->voucher->available->price_per_meal;
$expired_coupons_prices[] = $expired_coupon_price;
}
$array_prices_unique = array_count_values(array_column($expired_coupons_prices, 'price'));
foreach ($array_prices_unique as $key => $price)
{
$last_coupon_expired['date'] = date('Y-m-d');
$last_coupon_expired['quantity'] = $price;
$last_coupon_expired['price'] = (float) key($array_prices_unique);
$coupons_expired_today[] = $last_coupon_expired;
next($array_prices_unique);
}
if ($user->expired_coupons == NULL)
{
$coupons_expired_from_user = [];
}
else
{
$coupons_expired_from_user = json_decode($user->expired_coupons);
}
$user->expired_coupons = array_merge($coupons_expired_from_user,$coupons_expired_today);
$user->save();
}

Related

JSON update in PHP : duplication

I have a strange issue when I'm trying to update a json in my database.
This is my code :
// Update content of user cart
$contentJSON = json_decode($userCart['content'],true);
$newJSONContent;
$wineNotExist = true;
$index = 1;
foreach($contentJSON as $key) {
// Update content if wine is already in user cart
if ($key['wineId'] === $wineId) {
$contentObject->wineId = $wineId;
$contentObject->wineQuantity = $key['wineQuantity'] + $wineQuantity;
$dataIndex = strval($index);
$newJSONContent->$dataIndex = $contentObject;
$wineNotExist = false;
} else {
$contentObject->wineId = $key['wineId'];
$contentObject->wineQuantity = $key['wineQuantity'];
$dataIndex = strval($index);
$newJSONContent->$dataIndex = $contentObject;
}
$index++;
}
if ($wineNotExist) {
$dataKey = strval($index);
$contentObject->wineId = $wineId;
$contentObject->wineQuantity = $wineQuantity;
$newJSONContent->$dataKey = $contentObject;
}
So, I decided to build a new JSON and parse the former; moreover if json not contains the wineId we created a new data input in JSON but this section replaces previous key by the right one and create the right one as you can see in AJAX response here :
Response when it's the same wineId
{
"code": 200,
"status": "success",
"message": "This wine has been added to your cart",
"content": {
"1": {
"wineId": 2,
"wineQuantity": 3
}
},
"index": true
}
Response when wineId is not contains in cart
{
"code": 200,
"status": "success",
"message": "This wine has been added to your cart",
"content": {
"1": {
"wineId": 5,
"wineQuantity": 1
},
"2": {
"wineId": 5,
"wineQuantity": 1
}
},
"index": true
}
I don't understand why the instruction in if replaces previous value, do you have an idea why ?
When I use another variable name for contentObject in if instruction, the code works but why ? Because $contentObject is a local variable in foreach loop
Sorry for my english, I'm French.
It works with this code, so the problem is that $contentObject has the previous value whereas it's a local varibale, is it specific to PHP ?
// Update content of user cart
$contentJSON = json_decode($userCart['content'],true);
$newJSONContent;
$wineNotExist = true;
$index = 1;
foreach($contentJSON as $key) {
// Update content if wine is already in user cart
if ($key['wineId'] === $wineId) {
$contentObject=null;
$contentObject->wineId = $wineId;
$contentObject->wineQuantity = $key['wineQuantity'] + $wineQuantity;
$dataIndex = strval($index);
$newJSONContent->$dataIndex = $contentObject;
$wineNotExist = false;
} else {
$contentObject=null;
$contentObject->wineId = $key['wineId'];
$contentObject->wineQuantity = $key['wineQuantity'];
$dataIndex = strval($index);
$newJSONContent->$dataIndex = $contentObject;
}
$index++;
}
if ($wineNotExist) {
$contentObject=null;
$dataKey = strval($index);
$contentObject->wineId = $wineId;
$contentObject->wineQuantity = $wineQuantity;
$newJSONContent->$dataKey = $contentObject;
}

Accessing nested object within array in PHP (Laravel)

I am struggling for quite a while on how to access nested object.
$dt = Carbon::parse($year.'-'.$month.'-1');
$godziny = array();
$gs = $lekarz->od;
$gz = $lekarz->do;
$ile = $gz-$gs;
for($j=0; $j<4*$ile; $j++){
if($j%4==0){
$wm = "00";
}
else{
$wm = ($j%4)*15;
}
if($gs+floor(($j/4)) < 10){
$dz="0".$dz = $gs+floor(($j/4));
} else{
$dz = $gs+floor(($j/4));
}
$godziny[$j]['godzina'] = $dz;
$godziny[$j]['minuty'] = $wm;
if(!empty(Kolejka::where('data', 'LIKE', $year.'-'.$month.'-'.$day.' '.$dz.':'.$wm.'%')->get())){
$godziny[$j]['odbyta'] = Kolejka::where('data', 'LIKE', $year.'-'.$month.'-'.$day.' '.$dz.':'.$wm.'%')->get();
dd(get_object_vars($godziny[$j]['odbyta']));
// $godziny[$j]['pacjent'] = Pacjent::where('id', '=', $godziny[$j]['odbyta']->{0}->pacjent_id);
} else {
$godziny[$j]['odbyta'] = '';
}
}
Everything works except for the last part. It seems like whatever way i try to access this data ( by using $godziny[$j]['odbyta']['pacjent_id'] or by $godziny[$j]['odbyta']->pacjent_id) it just won't work. I really don't know what to do.
That's my [$j]['odbyta] data:
{
"id": 1,
"pacjent_id": "13",
"lekarz_id": "1",
"data": "2017-04-05 10:15:00",
"odbyta": "0",
"created_at": "2017-04-05 16:14:42",
"updated_at": "2017-04-05 16:14:42"
}
That is code that generates data with a pattern:
$j's max number is 36
$godziny[0]['godzina'] = $dz //That's for setting hour to array
$godziny[0]['godzina'] = $wm; //That's for assigning minutes
$godziny[0]['odbyta'] <- that's of value of object that i listed above
How can i possibly access data from this object?
so $godziny[0]['odbyta'] can give me an value of object it contains?
Can't you just use Model->where...first()? and than access it as object:
$godziny[$j]['odbyta'] = Kolejka::where('data', 'LIKE', $year.'-'.$month.'-'.$day.' '.$dz.':'.$wm.'%')->first();
$godziny[$j]['pacjent'] = Pacjent::where('id', '=', $godziny[$j]['odbyta']->pacjent_id);

Chart JS + Laravel - How to add 0 to array

Employees and Projects
I have a pivot table where my code is grabbing all the projects that an employee is assigned to and the stage they are in.
Stages
Waiting
In Progress
Launched
This works and I get the chart to show the data if the employee has projects in each stage. However, when there are not projects in every stage, the array gets messed up and the bar graph shows the data but in the wrong part. For example:
Array that works: [2, 4, 2]
2 Waiting
4 In Progress
2 Launched
Array that doesn't work: [5]
0 Waiting
0 In Progress
5 Launched
In the second case, since the array only has one value, the 5 is shown under Waiting and not launched. How do I add 0's and get the array to show [0, 0, 5]?
Thanks.
$projects = Project::join('employee_project', 'projects.id', '=', 'employee_project.project_id')
->where('employee_project.employee_id', $id)
->groupBy('stage')
->select('stage', DB::raw('count(*) as total'))
->orderByRaw('case
when stage = "Waiting" then 1
when stage = "In Progress" then 2
when stage = "Launched" then 3
end')
->get();
foreach ($projects as $project) {
$t[] = $project->total;
}
$t = json_encode($t);
Updated Code
foreach ($projects as $project) {
if ($project->stage == 'Waiting') {
$t[0] = $project->total;
} elseif ($project->stage == 'In Progress') {
$t[1] = $project->total;
} elseif ($project->stage == 'Launched') {
$t[2] = $project->total;
} else {
$t[] = 0;
}
}
$t = json_encode($t);
This updated code gives me an associative array like {"1": 4, "2": 5}. ChartJS can't use the associative array. It needs an array like [0, 4, 5].
Also, the associative array doesn't include the 0's.
NEW UPDATE
foreach ($projects as $project) {
if($project->total > 0) {
$t[] = $project->total;
} else {
$t[] = 0;
}
}
This doesn't work either. Any ideas?
So I figured it out. I just had to add an array initializing it. Here is the code:
$t = [0,0,0];
foreach ($projects as $project) {
if($project->stage === 'Waiting') {
$t[0] = $project->total;
} elseif($project->stage === 'In Progress') {
$t[1] = $project->total;
} elseif($project->stage === 'Launched') {
$t[2] = $project->total;
} else {
$t[] = $t;
}
}
$t = json_encode($t);

How to format json to what I need?

ok, Going to get this out of the way right now. I suck at php. I am building an angular app that is going to populate a mobile app with data from the database. I having it pull from the database just fine but I need the json formatted in a special way and I have no idea how to do it.
Using json_encode this is how it is coming from the database:
[
{
"id":"1",
"date":"2014-10-03",
"time":"2014-10-03 10:45:05",
"amount":"5"
},
{
"id":"2",
"date":"2014-10-03",
"time":"2014-10-03 12:21:05",
"amount":"2"
}
]
This is how I need it organized (this is just dummy data im using in on the angular side)
[
{
date: '2014-09-04',
feeding: [
{
id: '1',
time: '1409852728000',
amount: '3'
},
{
id: '2',
time: '1409874328000',
amount: '4'
},
]
},
{
date: '2014-09-05',
feeding: [
{
id: '3',
time: '1409915908000',
amount: '3.5'
},
{
id: '4',
time: '1409957908000',
amount: '5'
},
]
},
]
I needs to be seperated out and grouped by date. How would I go about doing this?
Airtech was just about there. Small update to the function though. The feeding value needs to be an array of objects rather than an object. You then need to push individual objects into that array.
function dateparse($in) {
$in = json_decode($in);
$out = array();
for ($i = 0; $i < sizeof($in); $i++) {
$date = $in[$i]->date;
$isFound = false;
for ($i2 = 0; $i2 < sizeof($out); $i2++) {
if ($date == $out[$i2]["date"]) {
// We've already run into this search value before
// So add the the elements
$isFound = true;
$out[$i2]["feeding"][] = array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount);
break;
}
}
if (!$isFound) {
// No matches yet
// We need to add this one to the array
$feeding = array("id" => $in[$i]->id, "time" => $in[$i]->time, "amount" => $in[$i]->amount);
$out[] = array("date" => $in[$i]->date, "feeding" => array($feeding));
}
}
return json_encode($out);
}
How about the following? I tested it on your json input example and it ran fine.
function parse($in)
{
$in = json_decode($in);
$out = array();
for ($i = 0; $i < sizeof($in); $i++) {
$date = $in[$i]->date;
$isFound = false;
for ($i2 = 0; $i2 < sizeof($out); $i2++) {
if ($date == $out[$i2]["date"]) {
// We've already run into this search value before
// So add the the elements
$isFound = true;
$out[$i2][]["feeding"] = array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount);
break;
}
}
if (!$isFound) {
// No matches yet
// We need to add this one to the array
$out[] = array("date" => $in[$i]->date, "feeding" => array(
"id" => $in[$i]->id,
"time" => $in[$i]->time,
"amount" => $in[$i]->amount));
}
}
return json_encode($out);
}
How about this ? This works fine and works as expected :) :-
function dateparse($var)
{
$counter=0; $var = json_decode($var); $date=array();
foreach($var as $key=>$value){foreach($value as $val1=>$val2)
{if($val1 == "date")
{foreach($value as $val3=>$val4)
{if($val3!="date") //because we don't want date again
{
$date[$val2]["feeding"][$counter][$val3] = $val4; continue;
}}continue;
}
}$counter++;}
return json_encode($date);}

MySQL to nested JSON

This is almost exactly what I want, but that question hasn't been answered and it's been a year. I've managed to get close, I think, but numbers are being printed as keys. In my example it shows up on line 47, but it is repeated for every "course_name" in the actual file.
[
{
"school_name": "Projects",
"terms": [
{
"term_name":"category_name#1",
"departments": [
{
"department_name":"sub_category_name1",
"department_code":"category code text here",
"courses":[
{
"course_name": "project1",
"course_code":"project 1 code text goes here",
"sections":[
{
"section_code":"mike",
"unique_id":"xxx#mail.com"
},
{
"section_code":"dan",
"unique_id":"xxx#gmail.com"
}
]
},
{
"course_name": "project2",
"course_code":"project 2 code text goes here",
"sections":[
{
"section_code":"steve",
"unique_id":"xxx#mail.com"
},
{
"section_code":"chris",
"unique_id":"xxx#gmail.com"
}
]
}
]
},
{
"department_name": "sub_category_name2",
"department_code":"sub category description text goes here..",
"courses": {
-->>> "69": {
"course_name": "project3",
"course_code":"project3 code text goes here ",
"sections":[
{
"section_code":"Alex",
"unique_id":"xxx#gmail.com"
}
]
}
}
}
]
}
]
}
]
Here is the query I am using and an example of data being returned.
SELECT school_name, term_name, department_name, department_code, course_code, course_name, section_code, magento_course_id
FROM schools INNER JOIN term_names ON schools.id=term_names.school_id INNER JOIN departments ON schools.id=departments.school_id INNER JOIN
adoptions ON departments.id=adoptions.department_id
"UCA-2" "SPRING 2013" "ACCOUNTING" "ACCT" "3315" "COST ACCOUNTING" "10258" 10311
What I have is being generated with this code.
$row_array = array();
$terms = array();
$departments = array();
$courses = array();
$h = 0;
$i = 0;
$j = 0;
while ($row = mysqli_fetch_assoc($fetch)) {
$row_array[$row['school_name']]['school_name'] = $row['school_name'];
$akey = array_search($row['term_name'], $terms);
if ($akey === FALSE) {
$m = $h++;
$terms[] = $row['term_name'];
$row_array[$row['school_name']]['terms'][$m]['term_name'] = $row['term_name'];
} else {
$m = $akey;
}
$key = array_search($row['department_code'], $departments);
if ($key === FALSE) {
$k = $i++;
$departments[] = $row['department_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_name'] = $row['department_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['department_code'] = $row['department_code'];
} else {
$k = $key;
}
$skey = array_search($row['course_code'], $courses);
if ($skey === FALSE) {
$l = $j++;
$courses[] = $row['course_code'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_name'] = $row['course_name'];
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['course_code'] = $row['course_code'];
} else {
$l = $skey;
}
$row_array[$row['school_name']]['terms'][$m]['departments'][$k]['courses'][$l]['sections'][] = array('section_code' => $row['section_code'], 'unique_id' => $row['magento_course_id']);
}
How do I generate this JSON without those numbers showing up?
I think you have some key & encoding problems. Too much key usage, excessive loops in your code. Maybe you should tidy your sql query.
Since you are setting keys for courses, JSON shows it.
Try removing the key after "['courses']" in your last line such as;
Change ['courses'][$l] to ['courses'][]
At the end, encode the array for JSON.
$result = json_encode($result);

Categories