Undefined offset PHP array - php

Hello I have a code that checks for duplicates inside an xml file:
XML:
<?xml version="1.0"?>
<profielen>
<profiel>
<voornaam>a</voornaam>
<achternaam>a</achternaam>
<adres>a</adres>
<postcode>a</postcode>
<plaats>a</plaats>
<email>a</email>
</profiel>
<profiel>
<voornaam>b</voornaam>
<achternaam>b</achternaam>
<adres>b</adres>
<postcode>b</postcode>
<plaats>b</plaats>
<email>b</email>
</profiel>
<profiel>
<voornaam>c</voornaam>
<achternaam>c</achternaam>
<adres>c</adres>
<postcode>c</postcode>
<plaats>c</plaats>
<email>c</email>
</profiel>
<profiel>
<voornaam>c</voornaam>
<achternaam>c</achternaam>
<adres>c</adres>
<postcode>cL</postcode>
<plaats>c</plaats>
<email>c</email>
</profiel>
</profielen>
I can select 6 checkboxes, the more are selected the more it filters. If I select firstname, only a,b and the first person with the name c can stay and the second one will be ignored.
Now I have this code:
$xml = simplexml_load_file('/xampp/htdocs/UploadifyZWP/uploads/profiel.xml');
//Load the xml file into an array
$myArray = $_REQUEST['checkboxarray'];
//Contains the selected value (firstname = 0,lastname = 1 etc..)
if(count($myArray) <1){
//If $myArray is empty it means no checkboxes are selected and there will be no filtering
count($xml);
}else{
$fields = $myArray;
//If at least one field is selected, this code runs:
switch(count($myArray)){
case 1:
//One checkbox selected
//Array where the profiles go withouth duplicates
$profile = array();
$passed = 0;
$teller = 0;
//Loops through all the profiles in the xml array
while($passed < count($xml)){
$add = false;
//Checks for all the selected values, 1 checkbox is selected so only 0 (firstname) is selected and goes into $field
foreach($fields as $field){
if(count($profile) < 1){
//If profile is empty, add the first profile from the xml array
$add = true;
}else {
if($profile[$teller][$field] != $xml->profiel[$teller][$field])
{
$add = true;
break;
}else{
$teller++;
$passed++;
}
}
}
if($add = true){
//toevoegen
$profile[$teller] = $xml->profiel[$teller];
$teller++;
$passed++;
}
}
echo count($profile);
print_r($profile);
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
break;
default: echo "error";
}
}
So I put all the correct profiles in $profile array and the duplicate will be ignored. Now for testing I print the array profiles to see if it did what it should do, but the outcome is not what I was looking for. The first one (a) will be added to $profiles, the second one (b) will not, the third one (c) is added again and the fourth (duplicate(d)) is not. Now if I add 2 more profiles (e,f), e will be added and f will not. Now I have troubles installing a debugger so I don't see where it is going wrong. I also get an error that says:
Notice: Undefined offset: 1 in C:\xampp\htdocs\UploadifyZWP\ontdubbelen.php on line 37
And
Notice: Undefined offset: 3 in C:\xampp\htdocs\UploadifyZWP\ontdubbelen.php on line 37
Does anyone see where it is going wrong and why?

On this line if($profile[$teller][$field] != $xml->profiel[$teller][$field]) you have specified a third level of a multidimensional array but your data has only 2 levels as shown below.
SimpleXMLElement Object
(
[voornaam] => a
[achternaam] => a
[adres] => a
[postcode] => a
[plaats] => a
[email] => a
)
Try this instead
if($profile[$teller] != $xml->profiel[$teller])

There are a few issues with this code, but the main one is that some of the logic in it is flawed.
I'll start by saying that the if statement if($add = true) will always return true, since you are assigning rather than comparing. You need to use if ($add == true) to perform a comparison.
Other than that, it's quite hard to say exactly what you're doing wrong, because it is a general failure in logic. The main issue comes down to the fact that, on the second iteration of your while loop (starting while($passed < count($xml))), the $profile array contains one element at index 0, (meaning that count($profile) < 1 returns false, but the value of $teller is now 1, since you incremented it in the first iteration. You then try to compare the value of $profile[$teller][$field], which fails, because there is no offset of 1 in your $profile array.
Edit
To check for the existence of an index in an array, you can use isset, for example
if (isset($profile[$teller]))

Related

Conditional unset from Guzzle response

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;

If Statement with Foreach not iterating through foreach

I am having an issue with my code - fairly new to PHP so any pointers would be appreciated.
I have the following code
foreach(findCustomAlerts($customerid) as $key=>$value){
echo "ID : ".$rifdid = $value['Catid']."<br>";
echo "Visits required per day : ".$visitsneeded= $value['Visits required']."<br>";
}
foreach(getTodaysVisits($device_id) as $rfid){
foreach($rfid as $key=> $read){
if($key ==$rifdid && $read < $visitsneeded) {
echo"<br>". $key." has not visited enough";
}
}
}
But it is not iterating through the foreach - it is only picking up the first values and then stopping :
ID: 1005
Visits required per day : 3
ID : 2089
Visits required per day : 5
2089 has not visited enough
This is the array that the foreach should be iterating through:
Array
(
[rfid_id] => Array
(
[2089] => 1
[1005] => 3
)
)
I have tried putting a variable in to count the iterations like so :
$i = 0;
foreach(getTodaysVisits($device_id) as $rfid){
foreach($rfid as $key[$i]=> $read){
if($key[$i] ==$rifdid && $read < $visitsneeded) {
echo"<br>". $key[$i]." has not visited enough";
$i++;
}
}
}
But it gives me the following errors :
Warning: Cannot use a scalar value as an array
Notice: Trying to access array offset on value of type int in
So not sure what the best course of action is, any advice greatly appreciated.
This looks like the structure that you are receiving from findCustomAlerts($customerid) in the first for-each loop is not what you are expecting, however the warnings don't give line numbers so I could be wrong.
In your code you have a $key that goes unused, then a $value that you treat as an array.
The warning message you get tells us that you can't use a scalar (or singular) value type as an array. We then get a notice telling us that when we try to use it as an array, either the offset 'Catid' or 'Visits required' is unavailable, likely due to the same reason. I suspect $value is more likely of type integer based on the array example you've shown (1,3).
Run a var_dump() on the output of the findCustomAlerts function and I think you'll understand the issue better.

Undefined offset error when iterating array after removing elements from it

I receive the following error message:
Undefined offset: 1
It points to this block of code:
$nbrProgrammingsRemoved = 0;
for($i = 0; $i<count($this->products); $i++){
if((($this->products[$i])->id)==$id){
array_splice($this->products, $i, 1);
for($j = 0; $j<count($this->programming); $j++){
/*ERROR LINE*/ if((($this->programming[$j]->out_prod_id)==$id) || (($this->programming[$j]->in_prod_id)==$id)){
$nbrProgrammingsRemoved++;
array_splice($this->programming, $j, 1);
}
}
return true;
}
}
return false;
Specifically, the error points to the innermost if-statement. (The one with "||" in it).
Now, important to note is that this error does not always occur. It only ever happens after the following code has been run:
foreach ($this->programming as $key => &$prog) {
if($prog->in_prod_id == $in_prod_id){
if($prog->in_index == $in_index){
unset($this->programming[$key]);
}
}
}
The purpose of this code is to iterate through my objects in my array and remove those associated with a certain ID. This does appear to work since the output on my website is as expected. It's only when I, after doing this, attempt to execute the first code-block that my error occurs.
I've tried troubleshooting this for a while now, but without success. Any ideas? Any more information that you need me to post?
Edit: For further clarification, if needed, the 1st code block iterates through an array to remove a single element of a specified ID. The 2nd code block iterates through another array and removes several elements.
As far as I understand, you have an array with indexes comming in a sequence:
$programming = array(
0 => ...,
1 => ...,
2 => ...,
);
At some point you unset one element, so you array looks like this:
$programming = array(
0 => ...,
2 => ...,
);
And then you're using a for loop to iterate over all numbers from 0 up to N-1 (0, 1, 2, 3, 4 ... to be precise) presuming that all indexes are filled.
I think the best solution is to use a foreach loop in this case as it will care about indexes automatically and bypass deleted items.

Incrementing an array's value is causing warnings in the log

I am trying to create an array that holds the count of each course we offer based on location and then instructor. Here is sample code
$courseCnt = array();
foreach($courseList as $course){
$courseCnt[$course['location']][$course['instructor']] += 1
}
This code creates the array properly and displays well but I get a bunch of warnings like:
Unidentified index "Orlando" for locations, Unidentified index "John
Smith" for instructor
I have found that if I just make it = 1 instead of += 1 the warnings go away but of course this makes every course for location/instructor 1 which is not good.
My next though was checking if it exists, if it doesn't, make it 1 and if it does += 1. Here is an example
if(isset($courseCnt[$course['location']][$course['instructor']]){
$courseCnt[$course['location']][$course['instructor']] += 1
}else{
$courseCnt[$course['location']][$course['instructor']] = 1
}
This results in the fatal error:
Cannot use string offset as an array
$course array structure is just a 2 dimensional array pulled from sql
Sample:
courseID location instructor
1 Orlando John Smith
2 Detroit Bill Murray
You are not checking if the location exists before checking for the instructor in your first line of the new version of the code. You need to check if it exists and create it in your $courseCnt array if it doesn't (as an empty array). After that, you can check for the instructor:
// Initialise the empty array
$courseCnt = array();
// Create location if not in array
if( ! isset($courseCnt[$course['location']])) {
$courseCnt[$course['location']] = array();
}
// Either increment the instructor or create with initial value of 1
if ( isset($courseCnt[$course['location']][$courseCnt[$course['instructor']]]) ) {
$courseCnt[$course['location']][$courseCnt[$course['instructor']]] += 1;
}
else
{
$courseCnt[$course['location']][$courseCnt[$course['instructor']]] = 1;
}
You've got a lot of square brackets going on in there, so you might find it easier to read if you use PHP's array_key_exists (documentation) instead of isset:
// Initialise the empty array
$courseCnt = array();
// Create location if not in array
if( ! array_key_exists($course['location'], $courseCnt)) {
$courseCnt[$course['location']] = array();
}
// Either increment the instructor or create with initial value of 1
if ( array_key_exists($course['instructor'], $courseCnt[$course['location']]) ) {
$courseCnt[$course['location']][$courseCnt[$course['instructor']]] += 1;
}
else
{
$courseCnt[$course['location']][$courseCnt[$course['instructor']]] = 1;
}

Push item into an array and replace php

i need to make an array like this
$privateMsgIdArray = array("idlistener" => $idlistener, "maxMsgId" => $lastMsgId);
I need to replace the maxMsgId to the corresponding idlistener, and if the idlistener that i pass doesn't not exist to create a new entry inside the array.
I am a but confused on how i am going to extract the maxMsgId value corresponding to an idlistener.
In other words i need to pass new values of idlisteners only once, and replace maxMsgId each time that they are not equal to the corresponing idlistener.
If the idlistener field doesn't exist create it (push into array).
I pass old array into a session and new array in the current run.
After the run i i replace them.
I believe this sounds a bit confusing though.
e.g
We have an array like this already:
[15][200]
next call maxMsgId is 210
array should be
[15][210]
next call we have a new listener id with maxMsgId 30
array should be
[15][210]
[16][30]
You should be able to accomplish this with a quick loop:
// your "new" values
$idListener = 15;
$maxMsgId = 210;
// loop over the array to see if it contains the `idlistener` you want
$end = count($privateMsgIdArray);
for ($i = 0; $i < $end; $i++) {
if ($privateMsgIdArray[$i]['idlistener'] == $idListener) {
// we found it! overwrite the `maxMsgId` field
$privateMsgIdArray[$i]['maxMsgId'] = $maxMsgId;
break;
}
}
if ($i == $end) {
// we reached the end of the array without finding the `$idListener`;
// add a new entry =]
$privateMsgIdArray[] = array(
'idlistener' => $idListener,
'maxMsgId' => $maxMsgId
);
}
This is a rather brute-force approach though and, if efficiency is something you're after, it would be wise to create a "cache"-style method of idlistener values and their index in the $privateMsgIdArray array.
For instance:
// key = idlistener, value = index in `$privateMsgIdArray`
$idCache = array(15 => 0, 16 => 1);
// check if the `$idListener` is in the cache
if (!isset($idCache[$idListener])) {
// it's not; add a new entry
$key = count($privateMsgIdArray);
$privateMsgIdArray[$key] = array(
'idlistener' => $idListener,
'maxMsgId' => $maxMsgId
);
// add the new index into the cache
$idCache[$idListener] = $key;
} else {
// it is in the cache; pull the corresponding index and set the `maxMsgId` =]
$privateMsgIdArray[$idCache[$idListener]]['maxMsgId'] = $maxMsgId;
}
Both of the approaches above could be converted into functions to make things "more portable" too.

Categories