PHP prevent foreach loop from overwriting object - php

This is the fourth time I've tried writing this question, so please bear with me.
I have a PHP object that comes from a DB Query which pulls back the following data:
[1] => stdClass Object
(
[eventId] => 11
[eventName] => Second Event
[...]
[eventChildren] => Array
(
[0] => stdClass Object
(
[childId] => 8
[childName] => Jane Doe
[...]
[gifts] => Array
(
[0] => stdClass Object
(
[giftId] => 73
[giftName] => My two front teeth
[childId] => 8
[userId] => 1
[eventId] => 11
)
[1] => stdClass Object
(
[giftId] => 74
[giftName] => Wasps
[childId] => 8
[userId] => 1
[eventId] => 11
)
)
)
)
)
)
I'm then running a massive series of foreach loops in order to compare the userId from the gifts array against the userId stored in the session cookie.
From these loops I'm creating an array of children and gifts that the user has selected.
The problem is this overwrites my main object rather than creating a new one.
The Loops:
$user = $this->session->userdata('user');
$tempEvents = $events;
$userSelection = array();
$flag = FALSE;
foreach ( $tempEvents as $i => $event )
{
if ( $i == 0 )
{
foreach ( $event->eventChildren as $child )
{
$userGift = array();
foreach ( $child->gifts as $gift )
{
if ( $gift->userId == $user['userId'] )
{
array_push($userGift, $gift);
$flag = TRUE;
}
}
$tempChild = $child;
$tempChild->gifts = $userGift;
if ( $flag )
{
array_push($userSelection, $tempChild);
$flag = FALSE;
}
}
}
}
If I print_r($events); it displays the edited list rather than it's full list of events. Is there a way to create a duplicate object and edit that rather than editing the original object?

The reason for the "overwriting" is $tempChild = $child;.
That will not deep copy the contents of $child but make both $tempChild and $child point towards the same data structure, which obviously isn't desirable in this case.
You should use clone as in the below example.
$tempChild = clone $child;
PHP: Object Cloning - Manual

Try
$tempEvents = clone $events;

Related

How to update an Associative Array

I do not know what is wrong with my php code. I want to have an Associative Array in the format. When I run my code I get this data. [KY] is an array in the [OH] array.
Array ( [Oh] => Array ( [state] => Oh ) [income] => 100 [count] => 1 [Ky] => Array ( [state] => Ky ) )
Array (
[OH] => Array
( [income] =>
[count] =>
)
[KY] => Array
( [income] =>
[count] =>
)
Here is my code
Example data in $array
Array ( [0] => Array (
[SurveyDate] => 1952-06-21
[Income] => 100
[CountyState] => Hamilton|Oh
[count] => 1 ) )
function update_array_value3( $array )
{
foreach ($array as $row)
{
$arrCountyState = explode( "|", $row['CountyState'] );
$key = $arrCountyState[1]; // OH or KY
if( !isset( $_SESSION['sIncome'][$key] ) )
{
$_SESSION['sIncome'][$key]['state'] = $key;
$_SESSION['sIncome'][$key]['income'] = $row['Income'];
$_SESSION['sIncome'][$key]['count'] = 1;
} else
{
$_SESSION['sIncome'][$key]['state'] = $key;
$_SESSION['sIncome'][$key]['income'] += $row['Income'];
$_SESSION['sIncome'][$key]['count'] += 1;
}
}
I can't tell you the root cause of the problem simply based on this snippet of code, but it seems $row either doesn't contain the data you expect it to, or doesn't contain any data.
In your code you reference $row['CountyState'], yet I don't see any array item called CountyState in $array.
Also, I'm not sure whether or not this is intentional, but in your foreach() loop it looks like $_SESSION['sIncome']['income'] and $_SESSION['sIncome']['count'] are being overwritten. Each time the loop encounters a new $key, it will overwrite those values.

hierarchial two dimetional php array from an two dimetional php

I have a multiD array containing all users like below.
Array
(
[0] => Array
(
[username] => santoshe62
[sponsor] => santoshe61
)
[1] => Array
(
[username] => santoshe63
[sponsor] => santoshe62
)
[2] => Array
(
[username] => santoshe65
[sponsor] => santoshe64
)
[3] => Array
(
[username] => santoshe67
[sponsor] => santoshe66
)
.............................
)
I want an array from this array containing hierarchical data of given user like below.
Array
(
[0] => Array
(
[username] => santoshe62
[sponsor] => santoshe61
)
[1] => Array
(
[username] => santoshe63
[sponsor] => santoshe62
)
)
I have tried
function parseTree($datas, $parent = 0){
$tree = array();
for($i=0, $ni=count($datas); $i < $ni; $i++){
if($datas[$i]['sponsor'] == $parent){
$tree[] = $datas[$i];
parseTree($datas, $datas[$i]['username']);
}
}
return $tree;
}
Can anybody help me by finding what is wrong in my code? Also please suggest, can I select only this hierarchical structure directly from MySQL? Now I am selecting all results from DB.
The problem is because of this statement in your function, $tree = array();. In each recursive function call, this $tree is getting initialized with an empty array. You have to declare it as static variable, so that it could get initialized only once and could retain its state in recursive function calls.
function parseTree($datas, $parent = 0){
static $tree = array();
...
}

Quickest way to check an array of classed for an item?

I have a class with values:
Array
(
[0] => stdClass Object
(
[id] => 1
[val] => one
)
[1] => stdClass Object
(
[id] => 2
[val] => two
)
[2] => stdClass Object
(
[id] => 3
[val] => three
)
)
What is the quickest way to search this array to see if there is an item with id = 2? I know this will work:
$hasTwo = false;
foreach ($arrayItems as $arrayItem) {
if ($arrayItem->id == 2) {
$hasTwo = true;
break;
}
}
if ($hasTwo) {
// do what I wanted to do...
}
Is there no easier way that requires less code that can do the same?
Perhaps
$hasTwo = array_filter(
$arrayItems,
function($value) {
return $value->id == 2;
}
);
but you'll need to test which is the faster, and the answer is probably your original code

Trying to parse through SQL data to make an easier-to-handle associative array

I'm using Wordpress for this, but it is not a Wordpress-centric issue, so I am asking here.
You can see a snippet of my code here: http://pastebin.com/Cbc8wKvB
<?php
function getFormIds()
{
global $wpdb;
$sql = "
SELECT a.id
FROM wp_rg_lead a
WHERE a.form_id = 10 AND a.payment_status = 'Approved'
";
$query = $wpdb->get_results($sql);
if($query)
return $query;
return false;
}
function getFormInfo($form_id)
{
global $wpdb;
$sql = "
SELECT *
FROM wp_rg_lead_detail
WHERE lead_id = $form_id
";
$query = $wpdb->get_results($sql);
if($query)
return $query;
return false;
}
$credit_card_form_ids = getFormIds();
if ( $credit_card_form_ids ) {
$entries = array();
foreach( $credit_card_form_ids as $entry) {
$single_entry = getFormInfo($entry->id);
if ( $single_entry ) {
$entry_array = array();
$full_array = array();
foreach( $single_entry as $entry ) {
$curr_array = array( $entry->field_number => strip_tags($entry->value));
$entry_array[$entry->field_number] = strip_tags($entry->value);
array_push($full_array, $entry_array);
}
}
}
#var_dump('full_array', $full_array);
}
Basically I'm running a DB query to grab all entry ID's that match a certain criterion. This returns an array of objects of single values. I then pass this array through a foreach() and try to extract/combine data to make it easier to work with.
Here is a print_r() of a $single_entry from the code above: http://pastebin.com/RZmfD2EU
single entry:
Array
(
[0] => stdClass Object
(
[id] => 1983
[lead_id] => 86
[form_id] => 10
[field_number] => 34
[value] => 695
)
[1] => stdClass Object
(
[id] => 1982
[lead_id] => 86
[form_id] => 10
[field_number] => 39
[value] => 0
)
[2] => stdClass Object
(
[id] => 1981
[lead_id] => 86
[form_id] => 10
[field_number] => 40.1
[value] => Yes
)
... etc etc.
With the code I provided, the final array seems to collapse somehow -- meaning I lose entries somewhere along the way.
Ideally I'd love the data to associate id's to their key => value pairs. Namely:
[id] => [lead_id]
[field_number#] => [field_number_value]
For a actual representation of the first few lines of data provided:
Array (
[0] =>
(
[id] => 86
[34] => 695
[39] => 0
[40.1] => Yes
...etc
)
)
Is there a better way to loop through and associate data than what I'm doing? I'm relatively new/bad at PHP and MySQL and would love some guidance.
I'm not sure if I'm understanding it right but if you want to assign values to specified keys…
if ( $single_entry ) {
$entry_array = array();
$full_array = array();
foreach( $single_entry as $entry ) {
$curr_array = array( $entry->field_number => strip_tags($entry->value));
$entry_array[$entry->field_number] = strip_tags($entry->value);
$lead_id = $entry['lead_id'];
$full_array[$lead_id] = $entry_array;
}
}

How can I create multidimensional arrays from a string in PHP?

So My problem is:
I want to create nested array from string as reference.
My String is "res[0]['links'][0]"
So I want to create array $res['0']['links']['0']
I tried:
$result = "res[0]['links'][0]";
$$result = array("id"=>'1',"class"=>'3');
$result = "res[0]['links'][1]";
$$result = array("id"=>'3',"class"=>'9');
when print_r($res)
I see:
<b>Notice</b>: Undefined variable: res in <b>/home/fanbase/domains/fanbase.sportbase.pl/public_html/index.php</b> on line <b>45</b>
I need to see:
Array
(
[0] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 1
[class] => 3
)
)
)
[1] => Array
(
[links] => Array
(
[0] => Array
(
[id] => 3
[class] => 9
)
)
)
)
Thanks for any help.
So you have a description of an array structure, and something to fill it with. That's doable with something like:
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
// unoptimized, always uses strings
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
array_create( $res, "[0]['links'][0]", array("id"=>'1',"class"=>'3') );
array_create( $res, "[0]['links'][1]", array("id"=>'3',"class"=>'9') );
Note how the array name itself is not part of the structure descriptor. But you could theoretically keep it. Instead call the array_create() function with a $tmp variable, and afterwards extract() it to achieve the desired effect:
array_create($tmp, "res[0][links][0]", array(1,2,3,4,5));
extract($tmp);
Another lazy solution would be to use str_parse after a loop combining the array description with the data array as URL-encoded string.
I have a very stupid way for this, you can try this :-)
Suppose your string is "res[0]['links'][0]" first append $ in this and then put in eval command and it will really rock you. Follow the following example
$tmp = '$'.'res[0]['links'][0]'.'= array()';
eval($tmp);
Now you can use your array $res
100% work around and :-)
`
$res = array();
$res[0]['links'][0] = array("id"=>'1',"class"=>'3');
$res[0]['links'][0] = array("id"=>'3',"class"=>'9');
print_r($res);
but read the comments first and learn about arrays first.
In addition to mario's answer, I used another function from php.net comments, together, to make input array (output from jquery form serializeArray) like this:
[2] => Array
(
[name] => apple[color]
[value] => red
)
[3] => Array
(
[name] => appleSeeds[27][genome]
[value] => 201
)
[4] => Array
(
[name] => appleSeeds[27][age]
[value] => 2 weeks
)
[5] => Array
(
[name] => apple[age]
[value] => 3 weeks
)
[6] => Array
(
[name] => appleSeeds[29][genome]
[value] => 103
)
[7] => Array
(
[name] => appleSeeds[29][age]
[value] => 2.2 weeks
)
into
Array
(
[apple] => Array
(
[color] => red
[age] => 3 weeks
)
[appleSeeds] => Array
(
[27] => Array
(
[genome] => 201
[age] => 2 weeks
)
[29] => Array
(
[genome] => 103
[age] => 2.2 weeks
)
)
)
This allowed to maintain numeric keys, without incremental appending of array_merge. So, I used sequence like this:
function MergeArrays($Arr1, $Arr2) {
foreach($Arr2 as $key => $Value) {
if(array_key_exists($key, $Arr1) && is_array($Value)) {
$Arr1[$key] = MergeArrays($Arr1[$key], $Arr2[$key]);
}
else { $Arr1[$key] = $Value; }
}
return $Arr1;
}
function array_create(&$target, $desc, $fill) {
preg_match_all("/[^\[\]']+/", $desc, $uu);
foreach ($uu[0] as $sub) {
if (! isset($target[$sub])) {
$target[$sub] = array();
}
$target = & $target[$sub];
}
$target = $fill;
}
$input = $_POST['formData'];
$result = array();
foreach ($input as $k => $v) {
$sub = array();
array_create($sub, $v['name'], $v['value']);
$result = MergeArrays($result, $sub);
}

Categories