PHP Undefined array key on existing - php

I'm dealing with Undefined array key on key that actually exists.
Problem is caused when I'm trying to execute array_sum($array['number']), with error
`
"Undefined array key "number""
I have a lot of objects in that array, but I'm sure that every object has that key.
I tried it to define it as object key, can't find it as well.
Also tried:
foreach ($a as $item) {
if(!array_key_exists('number', $item)){
return "do not exists";
}
}
it's not returning that string.

$sum = 0;
foreach ($array as $item) {
$sum += $item->number;
}
or
$numbers = array_column($array, 'number');
$sum = array_sum($numbers);

Related

How to get value attirbute value from php 2d session variable

I am having an php session array like
["cart"]["123"] = "Biscuit"
["cart"]["124"] = "Jam"
If I want to access the 2nd element I will access array_values($_SESSION["cart"])[$i]
where $i runs in for loop. If I want to get the values "123" and "124", how can i achieve it in a for loop with only "cart" and $i..?
foreach($_SESSION['cart'] as $key => $value)
{
echo $key; // your 123 or 124 key
}
This is an associative array easiest and best way is foreach because have to deal with key-value pairs rather than indexes(numbers).
foreach($arr['cart'] as $key => $val){
echo "$key<br/>";
}
I used a variable to hold values($arr)
But you can try for loop also:
$keys = array_keys($arr['cart']);
for ($keyindex = 0; $keyindex < count($keys); $keyindex++) {
$key = $keys[$keyindex];
echo $key."<br>";
}

php foreach with arrays and objects and redefining their value

I'm trying to foreach through an array of objects inside an array. I'm not receiving errors, but it seems not to be storing the new value I'm trying to establish. I've found many answers on here closely related to this question, but I'm not understanding, and I'm hoping someone can make this clearer.
Essentially, this converts kg to lbs.
$kg_conv = 2.20462262;
$weights = array($data['progress']->weight, $data['progress']->squats,
$data['progress']->bench, $data['progress']->deadlift);
foreach ($weights as $value) {
$value = $value * $kg_conv;
}
The values in the array come out unchanged. From what I've read, I should be using $data['progress'] and iterating through that, but I'm not understanding how to refer to only some of the elements inside instead of all of them. I also tried cutting out some redundancy by storing the objects in $progress instead of $data['progress'] but still not success.
UPDATE: The following has not worked
1
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
2
foreach ($weights as $key => &$value) {
$value = $value * $kg_conv;
}
3
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
it does not work because you do not modify data array, you only modify copy made from this array, which is another array in memory
Solution: (will work for object's fields too)
$kg_conv = 2.20462262;
$weights = ['weight', 'squats','bench', 'deadlift'];
foreach ($data['progress'] as $key=>&$value) {
if ( in_array($key,$weights)
$value = $value * $kg_conv;
}
$value contains only a copy of the array element.
You can pass the object by reference like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
Note the & before $value.
See References Explained in the php documentation or What's the difference between passing by reference vs. passing by value? here on stackoverflow.
Edit 2:
But note that this will only change the values in the $weights array, not your object stored in $data['progress'], as it's value has been copied into $weights. To achieve this, you can reference the object properties when constructing the data array in the following way (this step was commented out in my testcase code) :
$weights = array(&$data['progress']->weight, &$data['progress']->squats,
&$data['progress']->bench, &$data['progress']->deadlift);
Note the & operator again.
But probably the solution of maxpower is cleaner for your requirement.
Edit:
After your comment I created the following test case which works fine:
<?php
class foo {
public $test = 5;
public $test2 = 10;
}
$obj = new foo();
$obj2 = new foo();
$obj2->test = 3;
$data = array('progress' => $obj, 'p2' => $obj2);
// this copies the values into the new array
$weights = array($data['progress']->test, $data['progress']->test2);
// this makes a reference to the values, the original object will be modified
// $weights = array(&$data['progress']->test, &$data['progress']->test2);
var_dump($weights);
$kg_conv = 2.20462262;
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
var_dump($weights);
The result is:
array(2) {
[0]=>
int(5)
[1]=>
int(10)
}
array(2) {
[0]=>
float(11.0231131)
[1]=>
&float(22.0462262)
}
The PHP foreach manual describes this topic in great detail. To summarise why you are not seeing the results you expect, here is a short explanation.
Imagine you have an array $arr = ['one', 'two', 'three']. When you execute a foreach loop on this array, PHP will internally create a copy of your array:
foreach ($arr as $key => $value) {
$value = 'something'; // You are modifying the copy, not the original!
}
To modify the original array, you have two options.
Use the $key variable to access the element at given key in the original array:
$arr[$key] = 'something'; // Will change the original array
Tell PHP to use a reference to the original element in $value:
foreach ($arr as $key => &$value) {
$value = 'something'; // $value is reference, it WILL change items in $arr
}
Both approaches are valid; however, the second is more memory-efficient because PHP does not have to copy your array when you loop through it - it simply references the original.
In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference. In your example code should look like this:
foreach ($weights as &$value) {
$value = $value * $kg_conv;
}
But referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).
You can also use indexes to acces array value directly. This code works pretty fine too:
foreach ($weights as $key => $value) {
$weights[$key] = $value * $kg_conv;
}
More here: http://php.net/manual/en/control-structures.foreach.php

How to declare, insert and iterate a php associative array with an associative array as value?

I need to work with a hashtable which values can store variables like:
$numberOfItems
$ItemsNames
If I ain't wrong, that would mean another hash like array as value.
What should be the right syntax for inserting and iterating over it?
Is anything like:
$hash['anyKey']=>$numberOfItems=15;
$hash['anyKey']=>$ItemsNames=['f','fw'];
valid?
if there's no chance to have collusion in item name, you can use the name in key
$hash[$ItemsName] = $numberOfItems;
in the other case, use an integer for example as a key, then the different "attributes" you want as keys for the 2nd array
$hash[$integer]["count"] = $numberOfItems;
$hash[$integer]["name"] = $name;$
Then, for iterating (1st case):
foreach ($hash as $name => $number) {
echo $number;
echo $name;
}
or, 2nd case
foreach ($hash as $item) {
echo $item["name"];
echo $item["count"];
}
To create php array, which can be a hash table, you can do:
$arr['element'] = $item;
$arr['element'][] = $item;
$arr['element'][]['element'] = $item;
Other way:
$arr = array('element' => array('element' => array(1)));
To iterate over it use foreach loop:
foreach ($items as $item) {
}
It's also possible to create nested loops.
About your case:
$hash['anyKey']=>$numberOfItems=15;
$hash['anyKey']=>$ItemsNames=['f','fw'];
I would do:
$hash['anyKey']['numberOfItems'] = 15;
$hash['anyKey']['ItemsNames'] = array('f','fw');

how to add another attribute using foreach loop to an array of rows

I am using a foreach loop on an array of rows in a model file in CodeIgniter.
What i want to do is reflect the changes i make in every row ,in the foreach loop ,to the original array.
$unique = $this->db->get_where('list', array('item_index' => $item));
foreach ($unique->result_array() as $row)
{
$row["status"]= "Not Unique";
if($row["bid_amount"]==$amount)
{
if($count==0){ $row["status"]="Unique and Final"; }
else {$row["status"]="Unique but Not Final"; }
}
$count++;
}
return $unique;
I am adding another attribute to each row here and i want to echo this attribute corresponding to each row in a view file.
But i am getting error Undefined index: status.
How can i possibly reflect the changes in the array to be returned.
Assign the result_array() to a variable, iterate over it, but change the original array and not the local one. PHP's foreach comes in two flavours:
foreach($arr as $value) and foreach($arr as $key => $value)
Try this:
$results = $unique->result_array();
foreach ($results as $rK => $rV){
$results[$rK]["status"]= "Not Unique";
//other stuff.
}
return $results;
Alternatively, you can pass by reference:
foreach ($results as &$result) {
$result['status'] = "Not Unique";
}
See the PHP docs on arrays. Specifically Example 10.
In your foreach the $row refers to a variable that's local to the loop. Thus changing it does not affect the data in $unique.

Removing an item from object in a loop

I have a set of Db results that are stored in an object. I need to loop through the results and check a property (using another DB query) and then use an if statement to remove the item from the object. Here is a simplified version of what I'm attempting:
foreach ($products as $product) {
if(!$product->active) {
unset($product);
}
}
print_r($products);
However when I print_r the items are still in the object. I'm getting confused.
Thats expected behaviour. There are two main way of doing what you want
foreach ($products as $key => $product) {
if(!$product->active) {
unset($products[$key]);
}
}
Second way would be to use reference
foreach ($products as &$product) {
if(!$product->active) {
unset($product);
}
}
You need to understand that unsetting an object has no effect in php. First of all let me explain you a crucial detail with FOREACH:
if you do:
$a = array(1,2,3,4,5);
foreach($a as $b){
unset($b);
}
$a will be first copied in memory. Its not a brute copy per say, it only copies a reference to the data and augments the count of usage of the array(1,2,3,4,5) in memory. Inside of $b, you will have copies of the data found in $a. Therefore, unsetting it from memory only says, hey, unset $b from inside the copy of $a. Therefore, making no change at all in the real $a.
If you were to do:
$a = array(1,2,3,4,5);
foreach($a as $key => $b){
unset($a[$key]);
}
Then here you would have a copy of $a in memory. The Foreach would iterate (loop) on that copy and provide you with keys to each elements $a that gets copied into $b. When you unset($a[$key]) you tell php to affect the array in $a that got copied when the foreach started, but now, instead of affecting the copy, you are using the $key to reference an element in $a that truly exists in memory and that you will have access to.
Now for the second part, if we look at objects... unsetting an object has no effect because variables containing objects are only references to data in memory with a count. If you $a = new Object() and then $b = $a, you create a new reference to that object whilst keeping it intact (not copied).
If you were to unset($a), you would only unset the reference to the object and $b would still point to that object in memory. If you unset($b), you will then unset the object reference from memory because nothing points to it.
Hope that makes it clearer...
Good luck
You can't unset the variable itself. You need to use the foreach syntax that also gives you the item's key and use that to unset key on the array:
foreach ($products as $key => $product) {
if(!$product->active) {
unset($products[$key]);
}
}
Use this line instead:
foreach ($products as &$product)
try this:
// $id is the key, $product is the value
foreach ($products as $id => $product) {
if(!$product->active) {
unset($products[$id]);
}
}
Alternatively, you can change the loop from using a foreach and operate directly on the array using a for-loop as follows:
<?php
$o1 = new stdClass;
$o2 = new stdClass;
$o3 = new stdClass;
$o1->active = false;
$o2->active = true;
$o3->active = true;
$products = [$o1, $o2, $o3];
for($i=0, $max=count($products); $i < $max; $i++) {
if (!($products[$i]->active)) {
unset($products[$i]);
}
}
print_r($products);
// re-index:
$improvedProducts = array_values($products);
print_r($improvedProducts);
See live code.

Categories