Conditional unset from Guzzle response - php

I've seen a few questions and the ones worth referencing
How can i delete object from json file with PHP based on ID
How do you remove an array element in a foreach loop?
How to delete object from array inside foreach loop?
Unset not working in multiple foreach statements (PHP)
The last two from the list are closer to what I'm intending to do.
I've got a variable names $rooms which is storing data that comes from a particular API using Guzzle
$rooms = Http::post(...);
If I do
$rooms = json_decode($rooms);
this is what I get
If I do
$rooms = json_decode($rooms, true);
this is what I get
Now sometimes the group exists in the same level as objectId, visibleOn, ... and it can assume different values
So, what I intend to do is delete from $rooms when
group isn't set (so that specific value, for example, would have to be deleted)
group doesn't have the value bananas.
Inspired in the last two questions from the initial list
foreach($rooms as $k1 => $room_list) {
foreach($room_list as $k2 => $room){
if(isset($room['group'])){
if($room['group'] != "bananas"){
unset($rooms[$k1][$k2]);
}
} else {
unset($rooms[$k1][$k2]);
}
}
}
Note that $room['group'] needs to be changed to $room->group depending on if we're passing true in the json_decode() or not.
This is the ouput I get if I dd($rooms); after that previous block of code
Instead, I'd like to have the same result that I've shown previously in $rooms = json_decode($rooms);, except that instead of having the 100 records it'd give only the ones that match the two desired conditions.

If I am not totally wrong, then this should do the trick for you:
$rooms = json_decode($rooms);
$rooms->results = array_values(array_filter($rooms->results, function($room) {
return property_exists($room, 'group') && $room->group != "banana";
}));
Here is a verbose and commented version of this one above:
$rooms = json_decode($rooms);
// first lets filter our set of data
$filteredRooms = array_filter($rooms->results, function($room) {
// add your criteria for a valid room entry
return
property_exists($room, 'group') // the property group exists
&& $room->group == "banana"; // and its 'banana'
});
// If you want to keep the index of the entry just remove the next line
$filteredRooms = array_values($filteredRooms);
// overwrite the original results with the filtered set
$rooms->results = $filteredRooms;

Related

Foreach loop over array of objects Laravel

I'm receiving this array of objects and need to iterate over it, but the problem is that I need to get the value of the next item when its iterating, to compare the value of the current object with the next one, and if it's a different value, split this array in two.
So, I was doing it with next() php function:
//looking for the next register in the array
$next = next($finances);
//first array if exist different values
$aiuaEd = [];
//second array if exist different values
$aiua = [];
foreach ($finances as $finance) {
if ($finance->cnpj <> $next->cnpj) {
$aiua[] = $finance;
} else {
$aiuaEd[] = $finance;
}
}
This code works fine at some point, but then I got this error:
Trying to get property 'cnpj' of non-object in
I don't know why sometimes works well and sometimes don't, debugging this variables, I found that if my array have 2 objects inside only, when I'm looping over it, the $next->cnpj variable came as empty, and sometimes don't.
Can someone help me with this?
I solved it with a different approach, instead of using php next(), I first loop over this array saving the cnpj's into an array.
$cnpjs = [];
foreach($finances as $finance){
$cnpj[] = $finance->cnpj;
}
Then I use array_unique() to group this 2 differents CNPJ's and sort() to get the correct keys order.
//grouping cnpjs as unique, should exist only 2 keys
$cnpj = array_unique($cnpj);
//sort array keys to get in order
sort($cnpj);
Then I iterate over my $finances array again, but now I'm counting if this $cnpj array has more than 2 positions, which means that I have to split this data in two differents arrays.
foreach($finances as $finance){
if(count($cnpj) > 1){
if($finance->cnpj == $cnpj[1]){
$aiua[] = $finance;
}else{
$aiuaEd[] = $finance;
}
}else{
$aiuaEd[] = $finance;
}
}
I'm pretty sure that this is not the best approach for that problem, or at least the most optimized one, so I'm open for new approach's suggestions!
Just posting how I solved my problem in case anyone having the same one.
Notice that this approach is only usable because I know that will not exist more than 2 different's CNPJ's in the array.

Only show items with a particular criteria in an array

I am trying to show only items that meet a certain criteria in an array. At the moment I am outputting everything in the array.
What I've got so far:
$records = $d->get("FoundCount");
$result = array();
for($i = 1; $ <= $record; $i++){
// various array components
$show_published = $d->field(show_published); //this is the variable from the DB that will determine if the item is shown on the page. Yes/no string.
if($show_published == 'Yes'){
$results[] = new Result(//various array components, $show_published, //more things);
}
This seems to output all items, including the ones labeled as 'No' .
Any guidance would be great. I have only been using php for a few months now.
I'm not sure if you're familiar with composer and how to install / use php packages.
If you are, you can add illuminate/support package as a dependency for your project and use its Collection to filter records - something along the lines of:
use Illuminate\Support\Collection;
$collection = new Collection($records);
$outputArray = $collection->filter(function($object) {
return (string) $object->field('show_published') === 'Yes';
})->toArray();
https://laravel.com/docs/5.5/collections
After this, the $outputArray will contain only records that have show_published flag set to Yes.
Alternatively you could use php's native function array_filter in pretty much the same manner:
$outputArray = array_filter($records, function($object) {
return (string) $object->field('show_published') === 'Yes';
});
http://php.net/manual/en/function.array-filter.php
Here's a simple example on how to create a new filtered array based on the criteria of strings starting with the character 'b'. I'm not sure what your criteria is but you could certainly take this approach and modify it to suit your needs.
//Original array of things that are un-filtered
$oldArray = array("Baseball", "Basketball", "Bear", "Salmon", "Swordfish");
//An empty filtered array that we will populate in the loop below, based on our criteria.
$filteredArray = array();
foreach($oldArray as $arrayValue) {
//Our criteria is to only add strings to our
//filtered array that start with the letter 'B'
if($arrayValue[0] == "B")
{
array_push($filteredArray, $arrayValue);
}
}
//Our filtered array will only display
//our 3 string items that start with the character 'B'
print_r($filteredArray);
Hope it helps! If not, feel free to reach out.

PHP spontaneously creates associative array where indexed array is required - using PHP arrays with Highcharts

I'm using PHP to retrieve data from an SQL database to produce a stacked column chart in Highcharts. The idea is that I'm taking the following piece of code to retrieve values from my database. This code should generate an array which then gets encoded to JSON and passed to Highcharts; this code produces a single 'part' of a stacked column, and the index determines which vertical bar that part is in. (So in http://www.highcharts.com/demo/column-stacked, the index would represent which fruit, and the data in this series would represent one person/color.)
The issue is that when I run this code, instead of ending up with an indexed array of data grouped by category, such as
[12,13,14,15] where each item is a category, I end up with an associative array where the indexes I specified in the code are turned into a string key.
{"1":13,"0":12,"3":14, "2":13, "5":15}
Because my indexes are being interpreted as associative keys and not as the indexed locations of the data inside the array, the data is now being added to locations in the order that I retrieved the data, and not assigned to a location in the array based on the index I give. Highcharts assigns categories based on location in the array, and not on key, so all my data ends up in the wrong categories.
Is there a way to get PHP to treat my carefully collected indexes as indexes and not as keys, and add my data points in the location in the array indicated by the indexes? I'm kind of new to PHP, and Java and C++ - the languages I've worked with before - don't have associative arrays, so any help you can give me in explaining and fixing this undesired behavior would be much appreciated.
Code below.
$variable indicates what the data is being sorted into categories by, and $r is the variable representing the array of the SQL query, so $r['variable'] is the category of this data point, and $r['amount'] is the data point itself.
$found = -1;
//if this is the first set of data being collected
if (count($category['data']) == 0){
$category['data'][0] = $r[$variable];
$series1['data'][0] = floatval($r['amount']);
$count++;
$times1[0]++;
}
//if it's not the first set of data, find out if this category has been used before
else {
for ($x = 0; $x < count($category['data']); $x++){
if ($r[$variable] == $category['data'][$x]){
$found = $x;
break;
}
}
// if that category does not already exist, add it, and add the data
if ($found == -1) {
$times1[$count]++;
$category['data'][$count] = $r[$variable];
$series1['data'][$count] = floatval($r['amount']);
$count++;
}
else { //otherwise, add its data to the data already in the current category. This will eventually yield an average, with $times1[] as the divisor
$times1[$found]++;
$series3['data'][$found] = floatval((floatval($series3['data'][$found]) + floatval($r['amount'])));
}}
Go through with below code hope it will give some idea to resolve your problem --
<?php
$jsonstring = '{"1":13,"0":12,"3":14, "2":13, "5":15}';
$tempArr = json_decode($jsonstring, true);
asort(tempArr); // for sorting the array --
//run another foreach to get created an array --
$finArr = array();
foreach(tempArr as $key=>$val){
$finArr[] = $val;
}
$requiredjsonString = json_encode(finArr); // it will return your required json Array [12,13,14,15]
?>
Edit: I advice also set JSON_NUMERIC_CHECK flag in json_encode();

fetch data from model that is called in loop

I have a controller function in CodeIgniter that looks like this:
$perm = $this->job_m->getIdByGroup();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
What I need to do is list the data in the result in the view, but I get only the last value while using this method. How can I pass all the results to the view?
Store it in an array. Like this:
foreach($perm as $pe=>$p){
$result[] = $this->job_m->getDatapermission($p['id']);
}
Because $result is not an array...
try this:
$result=array();
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[] = $this->job_m->getDatapermission($pId);
}
$data['permission'] = $result;
Note:
My answer uses a counter to enable the display of a single group result when needed.
Guessing from your need to loop and display the value of $result, possibly, it is an array or object returned by $query->result(). Things could be a bit complex.
Example: if $perm is an array of 5 items( or groups), the counter assigns keys 1 - 5 instead of 0 - 4 as would [] which could be misleading. Using the first view example, you could choose to display a single group value if you wants by passing it via a url segment. Making the code more flexible and reusable. E.g. You want to show just returns for group 2, in my example, $result[2] would do just that else next code runs. See my comments in the code.
$perm = $this->job_m->getIdByGroup();
$counter = 1;
foreach($perm as $pe=>$p)
{
$pId = $p['id'];
$result[$counter] = $this->job_m->getDatapermission($pId);
$counter++;
}
$data['permission'] = $result;
As mentioned above Note:
I Added a Counter or Key so you target specific level. If the groups are:
Men, Women, Boys, Girls, Children; you'd know women is group two(2) If you desire to display values for just that group, you don't need to rewrite the code below. Just pass the group key would be as easy as telling it by their sequence. To display all the loop without restrictions, use the second view example. To use both, use an if statement for that.
###To access it you could target a specific level like
if(isset($permission)){
foreach($permission[2] as $key => $value){
echo $value->columnname;
}
###To get all results:
foreach($permission as $array){
foreach($array as $key => $value){
echo $value->columnname;
}
}
}

Filtering through several SQL searches to build a single array - need pointers

I'm new to web developing.
This is part of a phone service, and I'm trying to filter through 3 different arrays that are filled with strings from three database searches: $sfaa, $sfipc, and $sfuaa. I have to filter the three database arrays to locate available customer service agents. The output would be an array filled with the IVR_Number to dial.
Heres an example of the string: "'Id', 'IVR_Number', 'Market_Id'"
I have to explode the string in order to get my data from each value in the arrays. Then based on a one-to-many id in each string I have to check if the id from $sfaa is in $sfipc or $sfuaa. If not then I have to build an array with the filtered records, from there I have to locate a value from the exploded string in $sfaa that belongs to that id. I wrote the following code but theres got to be an easier way?? I hope.... The client has to wait for these results before moving forward. There is usually only 10 or 15 records.
This code works I'm just wondering if there is an easier way to do this
Any tips
// formalua needed to filter above results and fill $aadl array
// explode each active agent array
$activeagentsfec=0;
$aaivra= array();
$aaida= array();
foreach ($sfaa as $aavalue)
{
${'aadetails'.$activeagentsfec} = explode("'",$aavalue);
${'aaivr'.$activeagentsfec} = ${'aadetails'.$activeagentsfec}[5];
${'aaid'.$activeagentsfec} = ${'aadetails'.$activeagentsfec}[1];
array_push($aaivra, ${'aaivr'.$activeagentsfec});
array_push($aaida,${'aaid'.$activeagentsfec});
$activeagentsfec++;
}
// explode each inprogress call array
$activecallsfec=0;
$actida= array();
$acfida= array();
foreach ($sfipc as $acvalue)
{
${'acdetails'.$activecallsfec} = explode("'",$acvalue);
${'actid'.$activecallsfec} = ${'acdetails'.$activecallsfec}[5];
${'acfid'.$activecallsfec} = ${'acdetails'.$activecallsfec}[7];
array_push($actida, ${'actid'.$activecallsfec});
array_push($acfida, ${'acfid'.$activecallsfec});
$activecallsfec++;
}
// explode each unvailable agent
$unavailableagentsfec=0;
$uaaida= array();
foreach ($sfuaa as $uavalue)
{
${'uadetails'.$unavailableagentsfec} = explode("'",$uavalue);
${'uaaid'.$unavailableagentsfec} = ${'uadetails'.$unavailableagentsfec}[3];
array_push($uaaida, ${'uaaid'.$unavailableagentsfec});
$unavailableagentsfec++;
}
// create available agent array by id
$aaafec=0;
$aada= array();
foreach ($aaida as $aaidavalue)
{
if (in_array($aaidavalue,$actida,true))
$aaafec++;
elseif(in_array($aaidavalue,$acfida,true))
$aaafec++;
elseif(in_array($aaidavalue,$uaaida,true))
$aaafec++;
else
array_push($aada, $aaidavalue);
}
// available agent arry by ivr
$aadl= array();
foreach ($aada as $aadavalue)
{
$aaaivrsv= array_search($aadavalue,$aaida,true);
array_push($aadl,$aaivra[$aaaivrsv]);
}
Given what you were saying in the comments, I'll try to give you some useful thoughts...
You carry out much the same process to parse $sfaa, $sfipc, and $sfuaa - explode, get certain columns. If you had some way to abstract that process, with a generic function for the parsing, that returns the data in a better format, called three times on each array, you'd see better through your code.
In the same way, your process is tightly coupled to the current state of the data - e.g. ${'acdetails'.$activecallsfec}[5]; is your fifth item today, but will it always be? Something generic, where you seek an column by name, might save you a lot of trouble...
finally, when merging data, if the data is sorted before hand the merge can be a lot quicker - seeking N items in a list of M, with an unsorted list takes O(n*m) operations, but if both are sorted it's O(min(m,n)).
I've taken the time to go through your code... Unless you're usign some of its variables elsewhere, here is a shorter equivalent:
// formula needed to filter above results and fill $aadl array
// explode each active agent array
$aaivra= array();
$aaida= array();
foreach ($sfaa as $aavalue)
{
$a = explode("'",$aavalue);
array_push($aaivra, $a[5]);
array_push($aaida,$a[1]);
}
// explode each inprogress call array
$actida= array();
$acfida= array();
foreach ($sfipc as $acvalue)
{
$a = explode("'",$acvalue);
array_push($actida, $a[5]);
array_push($acfida, $a[7]);
}
// explode each unvailable agent
$uaaida= array();
foreach ($sfuaa as $uavalue)
{
$a= explode("'",$uavalue);
array_push($uaaida, $a[3]);
}
// create available agent array by id
$aada= array();
foreach ($aaida as $aaidavalue)
{
if (!in_array($aaidavalue,$actida,true) &&
!in_array($aaidavalue,$acfida,true) &&
!in_array($aaidavalue,$uaaida,true))
array_push($aada, $aaidavalue);
}
// available agent arry by ivr
$aadl= array();
foreach ($aada as $aadavalue)
{
$aaaivrsv= array_search($aadavalue,$aaida,true);
array_push($aadl,$aaivra[$aaaivrsv]);
}

Categories