Chart JS + Laravel - How to add 0 to array - php

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);

Related

PHP - join equal arrays and add count of arrays joined

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();
}

Laravel Session works on Chrome, Not on Iphone

I have created a system where users can search for payment solutions for their business here: http://104.236.45.72/
When you click an answer for a question, you'll notice that as you click through on chrome, you get a list at the top of previously answered questions.
When you view this same thing on your mobile device, you'll notice that the questions as the top only show ONE. It's like the session is not persisting on mobile. I have no idea why and I've tried changing the session driver from database to file and tried replacing all of the "$request->session->" references with "Session::", which leads to the same thing, it working on desktop and only showing one previous answer on mobile.
Here is the function being called when you answer a question on the fontend.
public function questions(Request $request, $id, $parentId, $question)
{
//Get the industry...
$data['industry'] = Industries::find($id);
//Get the parent level question and one child...
$data['parentQuestion'] = Questions::where('parentId', $parentId)->where('industryId', $id)->get();
if(count($data['parentQuestion']) > 0) {
foreach($data['parentQuestion'] as $pq) {
if($pq->parentId != 0) {
//How many steps are currently in the array?
if ($request->session()->has('lastSteps')) {
$hasLastSteps = TRUE;
}else {
$hasLastSteps = FALSE;
}
$stepCount = 1;
if($hasLastSteps == TRUE) {
$stepCount += count(Session('lastSteps'));
}
//Get the last steps ready...
$lsQuestion = Questions::find($question);
$lsAnswer = Questions::find($parentId);
$lsQ = array(
'unique' => uniqid(),
'questionId' => $question,
'question' => $lsQuestion->question,
'answer' => $lsAnswer->question,
'url' => '/'.$request->path(),
'stepCount' => $stepCount
);
$dup = 0;
//see if the session has a lastSteps array...
if ($hasLastSteps == TRUE) {
$temp = Session('lastSteps');
foreach($temp as $t) {
if($t['questionId'] == $question) {
$dup = 1;
}
}
}
//No duplicates exist, go ahead and add it to the session!
if($dup === 0) {
$request->session()->push('lastSteps', $lsQ);
}
}
//Grab its children...
if($pq->type === 'question') {
$data['children'] = Questions::where('industryId', $id)->where('parentId', $pq->id)->get();
}else {
//its an endpoint / answer!
}
}
}
//see if the session has a follow up array...
if ($request->session()->has('followUp')) {
$data['followUp'] = Session('followUp');
}else {
$data['followUp'] = array();
}
//see if the session has a lastSteps array...
if ($request->session()->has('lastSteps')) {
$data['lastSteps'] = Session('lastSteps');
}else {
$data['lastSteps'] = array();
}
return view('frontend.questions', $data);
}

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);

PHP equivalent of Excel vlookup on array

After looking for a built in function in php I couldn't find a similar function to Excel's vlookup function.
I need a function that takes in an array and a lookup value and return the required info. So for example:
<?php
$baseCalculationPrice = [
0 => 50, //for values <=500 but >0
500 => 18, //for values <=3000 but >500
3000 => 15, //for values <=5000 but >3000
5000 => 14, //for values >5000
];
//Examples
$numPages = 499;
echo vlookup($numPages,$baseCalculationPrice); //should output 50
$numPages = 500;
echo vlookup($numPages,$baseCalculationPrice); //should output 50
$numPages = 501;
echo vlookup($numPages,$baseCalculationPrice); //should output 18
$numPages = 3000;
echo vlookup($numPages,$baseCalculationPrice); //should output 18
$numPages = 3001;
echo vlookup($numPages,$baseCalculationPrice); //should output 15
$numPages = 5000;
echo vlookup($numPages,$baseCalculationPrice); //should output 15
$numPages = 5001;
echo vlookup($numPages,$baseCalculationPrice); //should output 14
function vlookup($value,$array){
//magic code
return ....;
}
?>
I'm stuck even with the logic behind such a function, so any help would be great - thanks.
function vlookup($lookupValue,$array){
$result;
//test each set against the $lookupValue variable,
//and set/reset the $result value
foreach($array as $key => $value)
{
if($lookupValue > $key)
{
$result = $value;
}
}
return $result;
}
function testDeductionRate(){echo $this->deductionRate('ks',300);//zone and time are parameter for deductionRate() }
//deduction will be acted as vlookup (rangeLookup true)
function deductionRate($zone,$time){
$actualRate = 0;
$allRate = array(
'tg'=>array(0=>0,20=>200,30=>300,40=>400,50=>500),
'ks'=>array(0=>0,20=>100,30=>200,40=>300,50=>400),
'pc'=>array(0=>0,20=>50,30=>100,40=>200,50=>300)
);
if(isset($allRate[$zone])){
$rate = $allRate[$zone];
foreach($rate as $key=>$val){
if($time>=$key) $actualRate = $val;
}
}else{
return -1; //-1 means error
}
return $actualRate;
}
Try this if you would like to query on multi dimension associative array:
function vlookup($lookup_vakue, $lookup_array, $lookup_column, $result_column)
{
foreach ($lookup_array as $item) {
if ($item[$lookup_column] == $lookup_vakue) {
return $item[$result_column];
}
}
return false;
}
Sample Data
$data =
[
['id'=>1,'price'=>100],
['id'=>2,'price'=>200],
['id'=>3,'price'=>300]
];
Query Option
$result = vlookup('2',$data, 'id','price');
Result:
200
$getbase= function($amount) use ($baseCalculationPrice)
{
return (end(array_filter(
$baseCalculationPrice,function ($key) use ($amount)
{
return $key < $amount;
},
ARRAY_FILTER_USE_KEY
)));
};
amount 150 result 50
amount 1500 result 18
amount 25000 result 14

Google Analytics PHP API (GAPI) non-mobile browsers

I am trying to display the top 5 of non-mobile browsers with GAPI.
I can't seem to find a way of doing this, is this even possible?
This is how I get the percentage of mobile visits:
$ga->requestReportData(GA_PROFILE_ID, array("isMobile"), array("visits"), '-visits', null, $startdate, $enddate);
foreach ($ga->getResults() AS $result) {
if ((string)$result == "Yes") $mobile["yes"] = $result->getVisits();
else $mobile["no"] = $result->getVisits();
}
This is how I ended up doing it:
public function getDevices($max = 5) {
$this->ga->requestReportData($this->profileid, array('mobileDeviceInfo'), array('visits'), '-visits', 'mobileDeviceInfo != (not set) && mobileDeviceInfo != (not provided)', $this->startdate, $this->enddate, 1, $max);
foreach ($this->ga->getResults() as $result) {
$device[] = (string)$result;
$visits[] = $result->getVisits();
}
if (!isset($device) OR !isset($visits)) {
$device[] = "Niet genoeg data beschikbaar";
$visits[] = "0";
}
$return = array("device" => $device, "visits" => $visits);
return $return;
}

Categories