I always did something like
e.g. from my last project in Laravel
foreach( $sections as $section )
{
$section->date = Carbon::parse($section->date)->diffForHumans();
}
And it worked well. Never problem with that, array was modified as I wanted
But now I did this
$events = $this->events;
foreach($events as $event)
{
$date = new \DateTime($event['date']);
$event['date'] = (int)$date->format('d');
echo $event['date'];
var_dump($event);
}
var_dump($events);
$this->events = $events;
And it doesn't work as I want, different values inside loop and outside loop.
I was looking what is bad and I found what it is about, to give & or do foreach $key => $value...
But it would be okay.
But it isn't.
Because I know. I remember. I did many times just something like
foreach($a as $b)
{
$b = .......
}
And it worked. But now it isn't.
So I don't understand. But I have to and want to.
I was searching for answer, but can find it.
Why for one time it works for me like that, and other time doesn't work and I need apersand or key => value playing?
Please give me understanding <3
Why one time it is working but another not.
foreach iterates over a copy of the array, so modifications to the array elements are only made to that temporary copy unless you create a reference:
foreach($a as &$b) {
$b = 'something';
}
Or modify the original array by key:
foreach($a as $k => $b) {
$a[$k] = 'something';
}
For an array of objects, the array is a copy but the objects in the copy are references to the original array. So modifications to the objects in the copy are reflected in the original array:
foreach($a as $b) {
$b->var = 'something';
}
Related
Hey in a recent project I got this working and was quite amazed that such a snipped works.
$parentRef = &$elements[$targetPath]->
{$contentTypeMap[$contentTypeIdMap[$contentTypeId]]};
if(is_array($parentRef)) {
$parentRef = &$parentRef[];
}
$parentRef = $element;
It was quite intuitive that it might work that way but what exactly is
$parentRef[] returning to make this work?
If I var_dump it, i get null.
Here is a simplified example which seems to work.
<?php
$arr = [1, 2];
$ref = &$arr[];
$ref = 3;
foreach($arr as $n) {
echo $n;
}
This example returns 123 just to verify that it works.
In your example $arr[] will create new element in array with NULL value. The ampersand is reference to this position, so when you store something to $ref, it will be stored in this new position, because $ref is just reference (something like pointer, but its not pointer!) to this new element in array
i have the following problem. i have a large array structure which i assign values from a sql statement:
$data[$user][$month]['id'] = $data->id;
$data[$user][$month]['company'] = $data->company;
...
...
and around 30 other values.
i need to clone this array ($data) and add a subarray like:
$data[$user][$month][$newsubarray]['id'] = $data->id;
$data[$user][$month][$newsubarray]['company'] = $data->company;
...
...
i need to clone it because the original array is used by many templates to display data.
is there a way to clone the array and add the subarray without assign all the values to the cloned array? this blows up my code and is very newbi, but works.
You can use array_map, check the live demo
if you want to pass parameter to array_map(), use this
array_map(function($v) use($para1, $para2, ...){...}, $array);
Here is the code,
<?php
$array =array('user'=> array('month'=>array('id' =>2, 'company' => 3)));
print_r($array);
print_r(array_map(function($v){
$arr = $v['month'];
$v['month'] = [];
$v['month']['newsubarray'] = $arr;
return $v;}
, $array));
You can iterate through the array with nested foreach loops.
It would look similar to this:
foreach ($data as $user=>$arr2) {
foreach ($arr2 as $month=>$arr3) {
foreach ($arr3 as $key=>$value) {
$data[$user][$month][$newsubarray][$key] = $value;
}
}
}
Your last level of array, you can create object, for holding data with implementing ArrayAccess. Then simply by reference, assign object in desire places. This way, you can hold 1 object and use it multi places, but if you change in one - this change in all.
Then you addictionaly, can implements __clone method to clone object correctly.
There are numerous questions out there about the safety implications of manipulating an array when using foreach on it. I can't find any questions on doing this in a while loop, though.
So I wonder, is it safe to do this? Below is an example script in PHP and I'm not sure if this is alright.
while ($item = array_pop($array)) {
findMoreItems($item, $array);
}
function findMoreItems($item, &$array) {
// Returns null if no more items are found
$newItem = someFuncFromServer($item);
if ($newItem) {
array_push($array, $newItem);
}
}
By safe I mean: can I be sure that no items are skipped in the loop?
Your code is essentially equivalent to :
$item = array_pop($array);
while ($item) {
findMoreItems($item, $array);
$item = array_pop($array)
}
function findMoreItems($item, &$array) {
// Returns null if no more items are found
$newItem = someFuncFromServer($item);
if ($newItem) {
array_push($array, $newItem);
}
}
Now if you rewrite this in the above way it is obvious that the code will not do anything like copy references or array points or anything like that which is what foreach does. foreach does that because it relies on the internal array pointer which array_pop and array_push do not.
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.
Every day , I have this pattern
- an array of objects
- i make a loop to traverse the array
foreach($arr as $obj){
$arrIds[] = $obj->Id;
$arrNames[] = $obj->Name;
}
I could build a function like arrayFromProperties($Array,$ProperyName) but I was wondering if you know a native php function to do this, or something similar, without having to write a new class/function for this.
As far as I know, you'll have to do this by your own.
Have you tried get_object_vars?
There isn't. It's not very hard to write, either. Feel free to reuse or adapt the following to your liking:
function soa_of_aos($aos)
{
$soa = array();
foreach ($aos as $i => $struct)
foreach ($struct as $field => $value)
if (!isset($soa[$field])) $soa[$field] = array($i => $value);
else $soa[$field][$i] = $value;
return $soa;
}