Extracting arrays into lists - php

I'm trying to extract each sub array using the foreach as list command.
Updated:
I am now trying this:
foreach ($data as $element) {
list($id,$ownerid,$owner,$coords,$name,$score,$citytype,$location) = $element;
findcontinent($coords);
echo $coords;
echo '<br>';
echo $cont;
echo '<br>';}
the function I am calling is as follows. I know this function works when I statically call a specific coordinate from the array $data[0]['coords'] for example.
function findcontinent($coords){
$tc2 = explode(":",$coords);
$tcx = (int)(trim($tc2[0],"'\'"));
$tcy = (int)(trim($tc2[1],"'"));
$tcx2 = round((($tcx)*(600/383)),0);
$tcy2 = round((($tcy)*(600/360)),0);
if($tcx2 < 100) // checking for continents ending with 0
{
$tcx3 = '0';
$xtrans = substr((string)$tcx3,0,1);
}
else
{
$xtrans = substr((string)$tcx2,0,1);
}
if($tcy2 < 100) // checking for continents starting with 0
{
$tcy3 = '0';
$ytrans = substr((string)$tcy3,0,1);
}
else
{
$ytrans = substr((string)$tcy2,0,1);
}
$cont = C.$ytrans.$xtrans;
return($cont);
}
I then want to run a set of SQL commands to update a DB. Do I have the correct syntax?
My array is as follows - sample. The actual datasets could be dynamic, many individual sub arrays?
[data] => Array
(
[0] => Array
(
[id] => 16515340
[owner_id] => 3475
[owner] => Player1
[coords] => '268:252
[name] => AC2013
[score] => 11863
[city_type] => castle
[location] => land
)
[1] => Array
(
[id] => 16515335
[owner_id] => 3475
[owner] => Player1
[coords] => '263:252
[name] => AC2013
[score] => 7
[city_type] => castle
[location] => water
)
[2] => Array
(
[id] => 17891610
[owner_id] => 3523
[owner] => Player2
[coords] => '282:273
[name] => City of Repoman9900
[score] => 1978
[city_type] => castle
[location] => water
)
[3] => Array
(
[id] => 10616856
[owner_id] => 73
[owner] => Player2
[coords] => '024:162
[name] => 1killer
[score] => 1308
[city_type] => castle
[location] => water
)
[4] => Array
(
[id] => 10813465
[owner_id] => 2862
[owner] => Player3
[coords] => '025:165
[name] => City of vuvuzea991
[score] => 1091
[city_type] => castle
[location] => land
)
[5] => Array
(
[id] => 17367317
[owner_id] => 84
[owner] => Player4
[coords] => '277:265
[name] => Dreadland
[score] => 776
[city_type] => castle
[location] => water
)
[6] => Array
(
[id] => 2162850
[owner_id] => 2989
[owner] => Player5
[coords] => '162:033
[name] => City of Dinoeyez
[score] => 157
[city_type] => castle
[location] => water
)
[7] => Array
(
[id] => 2818192
[owner_id] => 556
[owner] => Player6
[coords] => '144:043
[name] => City of wildfire123
[score] => 7
[city_type] => castle
[location] => water
)
)
Since it looks like associative arrays cannot be exploded into lists, which would have been nice, trying to run this loop to extract even 1 record, and failing
$count = 0;
// loop to cycle through array
foreach($data as $data=>$inner_array){
$c2 = (string)$count;
$id = $data[$count]['id'];
echo $id;
echo '<br>';
echo $count;
echo '<br>';
//then increment counter and move to next
$count = $count+1;
}
The counters return just fine, but I cannot seem to parse any of the variables in the sub-array. Echo output is as follows:
<br>0<br><br>1<br><br>2<br><br>3<br><br>4<br><br>5<br>
The data set I am using right now is 6 sub-arrays, so I know it is going through the loop correctly.

foreach ($data as list($id,$ownerid,$owner,$coords,$name,$score,$citytype,$location)) {
// commands
}
Since this use of list is only allowed in the beta version of PHP, the more portable syntax requires two steps:
foreach ($data as $element) {
list($id,$ownerid,$owner,$coords,$name,$score,$citytype,$location) = $element;
// commands
}
foreach ($data=>inner_array as xxx) is not valid. The var=>var syntax is only valid after as, not before it. I'm not sure why you have nested for loops -- there's only one array you need to iterate over.
I would be very wary of using this syntax when the sub-arrays are associative arrays. List assignment is based on the order of elements in the sub-array, it doesn't try to match variable names with keys. So if you have a sub-array where the owner_id element is before the id element, the list assignment will set $id to the owner ID, and $owner_id to the ID. The order of elements in an associative array is the order they were added to the array (unless you've used a function to rearrange them, such as array_sort() or array_splice()), so unless you're sure you always add keys in the same order this can be dangerous.
UPDATE:
List assignment like this doesn't work with associative arrays. According to PHP list documentation:
list() only works on numerical arrays and assumes the numerical indices start at 0.
So you'll need to assign the variables individually:
foreach ($data as $element) {
$id = $element['id'];
$owner_id = $element['owner_id'];
// and so on
}

Related

Removing parts of a multidimensional array that do not have a key that matches a separate array?

I have an array that is full of IDs that will match corresponding IDs in a separate array which is larger in terms of indices. I would like to first search through the larger array using the IDs from the smaller array and eliminate any indices that do not appear in the smaller array, and then place values present in the arrays that do match in my initial, smaller array. I have tried various nested for loops (come close, but does not get me there) but I can't seem to wrap my head about some array problems in general.
First array will look something like this:
Array
(
[0] => Array
(
[roleID] => 5b6468a500277c71b98405b1f140991c
[name] =>
[description] =>
[rate] =>
[hours] =>
[total] =>
)
[1] => Array
(
[roleID] => 5b6468a500277c74f6b2c065436b7d17
[name] =>
[description] =>
[rate] =>
[hours] =>
[total] =>
)
[2] => Array
(
[roleID] => 5b6468a500277c7697ba21928129e3af
[name] =>
[description] =>
[rate] =>
[hours] =>
[total] =>
)
)
Second array will look something like this
Array
(
[0] => stdClass Object
(
[ID] => 5b6468a500277c71b98405b1f140991c
[name] => CED
[objCode] => ROLE
[description] => CED
)
[1] => stdClass Object
(
[ID] => 5b6468a500277c74f6b2c065436b7d17
[name] => AD
[objCode] => ROLE
[description] => AD
)
[2] => stdClass Object
(
[ID] => 5b6468a500277c7697ba21928129e3af
[name] => AMG
[objCode] => ROLE
[description] => AMG
)
[3] => stdClass Object
(
[ID] => 5b6468a500277c77071c32c0bb2bae04
[name] => AP
[objCode] => ROLE
[description] => AP
)
[4] => stdClass Object
(
[ID] => 5b6468a500277c787e9680625c74ca80
[name] => AST
[objCode] => ROLE
[description] => AST
)
[5] => stdClass Object
(
[ID] => 5b6468a500277c79c0eddb8c14cc9f83
[name] => ASV
[objCode] => ROLE
[description] => ASV
)
)
I want to match the roleID in the first ID with the ID in the second array, then take the 'name' and 'description' keys and put it in the first array in the position it belongs. I have gotten close with the below code, but either a bunch of the arrays get misordered, or the 'name' and 'description' fields are the exact same for every index.
$projectUserRoleIDs = $client->get('project', $myProjectName, array('projectUserRoles:roleID'));
$projectUserRoleIDs = $projectUserRoleIDs->projectUserRoles;
$roleIDs = [];
for($a = 0; $a < count($projectUserRoleIDs); $a++)
{
$roleIDs[$a]['roleID'] = $projectUserRoleIDs[$a]->roleID;
// Get array of entire list of roles that are available in Workfront
// The roles:name category has all of the acronyms for each role, which can appear in an invoice
// The roles:description category has all of the full length names
$projectRoles = $client->get('project', $myProjectName, array('roles:name', 'roles:description'));
$projectRoles = $projectRoles->roles;
$roleLoop = [];
for($b = 0; $b < count($projectUserRoleIDs); $b++)
{
$roleLoop[] = $projectUserRoleIDs[$b]->roleID;
}
foreach($roleLoop as $key => $value) {
for($x = 0; $x<count($projectRoles); $x++)
{
if($projectRoles[$x]->ID === $value)
{
$name = $projectRoles[$x]->name;
$description = $projectRoles[$x]->description;
$roleIDs[$x]['name'] = $name;
$roleIDs[$x]['description'] = $description;
}
}
}
$roleIDs[$a]['rate'] = '';
$roleIDs[$a]['hours'] = '';
$roleIDs[$a]['total'] = '';
}
In the end I want my first array to look like this
Array
(
[0] => Array
(
[roleID] => 5b6468a500277c71b98405b1f140991c
[name] => CED
[description] => CED
[rate] =>
[hours] =>
[total] =>
)
[1] => Array
(
[roleID] => 5b6468a500277c74f6b2c065436b7d17
[name] => AD
[description] => AD
[rate] =>
[hours] =>
[total] =>
)
And so on... any help is appreciated and thank you.

PHP foreach injecting new index out of order on some iterations

I have this method that will take a single dimension array and transform it into a multi-dimensional array. It's an adjacency list of categories. I'm injecting an enumerated path as I go. It works 90% of the time.
public function fnExpandArray($aData){
$aNested = array();
foreach($aData as &$aCat){
if(isset($aData[$aCat['parent_id']])){
$aData[$aCat['parent_id']]['sub'][$aCat['id']] = &$aCat;
$aData[$aCat['parent_id']]['sub'][$aCat['id']]['path'] = $aData[$aCat['parent_id']]['path'] . '_' . $aCat['id'];
} else {
$aNested[$aCat['id']] = &$aCat;
$aNested[$aCat['id']]['path'] = $aCat['id'];
}
}
unset($aCat);
return $aNested;
}
This works OK 90% of the time, however the "path" index that is being injected is sometimes being injected after the "sub" index and causing the enumerated path to be calculated incorrectly. Example:
Correct:
[18] => Array
(
[id] => 18
[parent_id] => 1
[title] => Category 1
[path] => 1_18
[sub] => Array
(
[150] => Array
(
[id] => 150
[parent_id] => 18
[title] => Category 2
[path] => 1_18_150
But in some iterations it'll inject 'path' after 'sub' and the routine will fail.
Fail:
[45] => Array
(
[id] => 45
[parent_id] => 2
[sub] => Array
(
[10] => Array
(
[id] => 10
[parent_id] => 45
[sub] => Array
(
[152] => Array
(
[id] => 152
[parent_id] => 10
[title] => Category 1
[path] => _152
)
[79] => Array
(
[id] => 79
[parent_id] => 10
[title] => Category 2
[path] => _10_79
)
)
[title] => Dryers
[path] => _10
Note how path and title are injected after the sub injection. Any idea why?
This method rewrite resolved my issue. Made multiple passes on the array.
public function fnExpandTaxonomy(&$aData) {
$aTree = array();
// Loop original flat array, build associative and inject additional indices as required.
foreach($aData as $iKey => &$aCat){
$aTree[$aCat['id']] = &$aCat;
$aTree[$aCat['id']]['level'] = 0;
$aTree[$aCat['id']]['path'] = $aCat['id'];
$aTree[$aCat['id']]['sub'] = array();
}
// Loop - Add children to parents.
foreach($aTree as $iKey => &$aCat) {
if(!$aCat['parent_id']) continue;
unset($aCat['level'],$aCat['path'],$aCat['sub']);
$aCat['level'] = $aTree[$aCat['parent_id']]['level']+1;
$aCat['path'] = $aTree[$aCat['parent_id']]['path'].'_'.$aCat['id'];
$aTree[$aCat['parent_id']]['sub'][$aCat['id']] = &$aCat;
}
// Loop again, remove any items that don't have a parent of 0;
foreach($aTree as $iKey => &$aCat) {
if(!$aCat['parent_id']) continue;
unset($aTree[$iKey]);
}
unset($aCat);
return $aTree;
}
Big thank you to pyson, whose answer (below) in another similar thread helped me out.
create array tree from array list

What is the correct way to write an SQL statement to push data rows for this array?

I am trying to push array data to a MySQL database using foreach(). I'm quite a novice at PHP & mysql, so been working through parsing this data to PHP from an Ajax script, now just need to manipulate the data.
What is the correct syntax to push this data into SQL so that each dataset in the array goes to a seperate row?
i am trying to use foreach, but the complexity is that the array itself can change in size and the second complexity is that the data itself may be refreshed (i.e same id new values on a new day), so I want to build in some intelligence to update info not just append; and also to backup old data to another table.
is this syntax correct?
$sql = "INSERT INTO table1 (col1, col2) VALUES ";
foreach($rows as $i=>$row) {
if ($i>0) {
$sql .= sprintf(",(%s,%s)", $row["col1_value"], $row["col2_value"]);
} else {
$sql .= sprintf("(%s,%s)", $row["col1_value"], $row["col2_value"]);
}
}
mysql_query($sql);
The data in the array is as follows - this is only part of a multidimensional array, but I have figured out how to manipulate the rest of the array to my needs.
The only other thing I need to do is figure out a way to take the coords field and manipulate it as follows
Extract x & y data from coords
Multiple x & y by 600/386
Reverse x & y and take the first digit of each coordinate to create a new value y[1]x[1].
For this I tried just on the first data set, as follows, but I am inexperienced in data handling on PHP. Pretty sure it is wrong.
$testcoords = $_POST['data'][0]['coords'];
list($x,$y) = explode(“:”,str_replace(“’”,“”,$testcoords));
$xtrans = number_format($x*600/386,$decimals=null);
$ytrans = number_format($y*600/386,$decimals=null);
$cont = “C”.$ytrans[0].$xtrans[0]
So to summarize, three questions
How do I transfer data into a table, with rows for each individual dataset in the [data] array?
How do overwrite and archive any existing values in the table rather than simply concatenating?
How do I manipulate one specific string to return a custom variable as defined above?
[data_type] => city
[data] => Array
(
[0] => Array
(
[id] => 16515340
[owner_id] => 3475
[owner] => Player1
[coords] => '268:252
[name] => AC2013
[score] => 11863
[city_type] => castle
[location] => land
)
[1] => Array
(
[id] => 16515335
[owner_id] => 3475
[owner] => Player1
[coords] => '263:252
[name] => AC2013
[score] => 7
[city_type] => castle
[location] => water
)
[2] => Array
(
[id] => 17891610
[owner_id] => 3523
[owner] => Player2
[coords] => '282:273
[name] => City of Repoman9900
[score] => 1978
[city_type] => castle
[location] => water
)
[3] => Array
(
[id] => 10616856
[owner_id] => 73
[owner] => Player2
[coords] => '024:162
[name] => 1killer
[score] => 1308
[city_type] => castle
[location] => water
)
[4] => Array
(
[id] => 10813465
[owner_id] => 2862
[owner] => Player3
[coords] => '025:165
[name] => City of vuvuzea991
[score] => 1091
[city_type] => castle
[location] => land
)
[5] => Array
(
[id] => 17367317
[owner_id] => 84
[owner] => Player4
[coords] => '277:265
[name] => Dreadland
[score] => 776
[city_type] => castle
[location] => water
)
[6] => Array
(
[id] => 2162850
[owner_id] => 2989
[owner] => Player5
[coords] => '162:033
[name] => City of Dinoeyez
[score] => 157
[city_type] => castle
[location] => water
)
[7] => Array
(
[id] => 2818192
[owner_id] => 556
[owner] => Player6
[coords] => '144:043
[name] => City of wildfire123
[score] => 7
[city_type] => castle
[location] => water
)
)
[sender] => Array
(
[world] => Array
(
[id] => 232
[name] => Server 4
[number] => NaN
)
[alliance] => Array
(
[id] => 2
[name] => Alliance2
)
[player] => Array
(
[id] => 98
[name] => SuperUser
)
[browser] => Array
(
[type] => Chrome
[version] => 25.0.1364.160
)
[aix_version] => 1.00
)
)
The problems I see:
foreach($rows as $i=>$row) {
$sql = "INSERT INTO table1 (col1, col2) VALUES "; //reinitialize here.
if ($i>0) { //Why have the if statement, the results of the conditions are the same.
$sql .= sprintf("('%s','%s')", $row["col1_value"], $row["col2_value"]); //add quotation marks for string values, remove the comma.
} else {
$sql .= sprintf("(%s,%s)", $row["col1_value"], $row["col2_value"]);
}
mysql_query($sql); //execute the statement here.
}
Your other questions:
How do overwrite and archive any existing values in the table rather than simply concatenating?
To overwrite you do an update statement, the MySql website gives hints to syntax.
To archive, you will need to create an archive table that is pretty much a duplicate of the table being archived and insert/update that table.
In this context, I am not sure what you mean by concatenation, it does not really apply to databases that are normalized.
How do I manipulate one specific string to return a custom variable as defined above?
Ah gonna skip that one, it is a lot to ask in one post.

Get value in mutli array

How would i get the value of a key in an array?
The array is done by google shopping api which is:
// Valid source values are "public", "cx:cse", and "gan:pid"
// See http://code.google.com/apis/shopping/search/v1/getting_started.html#products-feed
$source = "public";
// For more information about full text search with the shopping API, please
// see http://code.google.com/apis/shopping/search/v1/getting_started.html#text-search
$query = "\"mp3 player\" | ipod";
//The order in which the API returns products is defined by a ranking criterion.
// See http://code.google.com/apis/shopping/search/v1/getting_started.html#ranking
$ranking = "relevancy";
$results = $service->products->listProducts($source, array(
"country" => "UK",
"q" => $query,
"rankBy" => $ranking,
));
print "<h1>Shopping Results</h1><pre>" . print_r($results, true) . "</pre>";
I have the following array which outputs:
Shopping Results
Array
(
[kind] => shopping#products
[etag] => "*********"
[id] => tag:google.com,2010:shopping/products
[selfLink] => https://www.googleapis.com/shopping/search/v1/public/products?country=UK&q=iphone&rankBy=relevancy
[nextLink] => https://www.googleapis.com/shopping/search/v1/public/products?country=UK&q=iphone&rankBy=relevancy&startIndex=26
[totalItems] => 771622
[startIndex] => 1
[itemsPerPage] => 25
[currentItemCount] => 25
[requestId] => 0CMjH976CqbECFYNWtAodLRwAAA
[items] => Array
(
[0] => Array
(
[kind] => shopping#product
[id] => tag:google.com,2010:shopping/products/5735617/11254757413841304510
[selfLink] => https://www.googleapis.com/shopping/search/v1/public/products/5735617/gid/11254757413841304510
[product] => Array
(
[googleId] => 11254757413841304510
[author] => Array
(
[name] => Amazon.co.uk
[accountId] => 5735617
)
[creationTime] => 2012-05-04T05:03:50.000Z
[modificationTime] => 2012-07-20T02:02:16.000Z
[country] => GB
[language] => en
[title] => Apple iPod touch 8GB - Black - 4th Generation (Latest Model - Launched Sept 2010)
[description] => Apple iPod touch 8GB - Black - 4th Generation (Latest Model - Launched Sept 2010)
[link] => http://www.amazon.co.uk/dp/B0040GIZTI/ref=asc_df_B0040GIZTI8843997?smid=A1YZ4RXO7GUOYN&tag=googlecouk06-21&linkCode=asn&creative=22218&creativeASIN=B0040GIZTI
[brand] => Apple
[condition] => new
[gtin] => 00885909394739
[gtins] => Array
(
[0] => 00885909394739
)
[mpns] => Array
(
[0] => MC540BT/A
)
[inventories] => Array
(
[0] => Array
(
[channel] => online
[availability] => inStock
[price] => 135.95
[shipping] => 1.99
[currency] => GBP
)
)
[images] => Array
(
[0] => Array
(
[link] => http://ecx.images-amazon.com/images/I/41p2rNmazRL.jpg
[status] => available
)
)
)
)
[1] => Array
(
[kind] => shopping#product
[id] => tag:google.com,2010:shopping/products/5735617/4597224105326146239
[selfLink] => https://www.googleapis.com/shopping/search/v1/public/products/5735617/gid/4597224105326146239
[product] => Array
(
[googleId] => 4597224105326146239
[author] => Array
(
[name] => Amazon.co.uk
[accountId] => 5735617
)
[creationTime] => 2012-05-04T05:03:50.000Z
[modificationTime] => 2012-07-20T02:02:16.000Z
[country] => GB
[language] => en
[title] => SanDisk Sansa Clip+ 8GB MP3 Player with Radio and Expandable MicroSD/SDHC Slot - Black
[description] => 8 GB memory Digital FM-tuner with 40 preset radio stations Extendable microSD/microSDHC card slot
[link] => http://www.amazon.co.uk/dp/B002NX0ME6/ref=asc_df_B002NX0ME68843997?smid=A3P5ROKL5A1OLE&tag=googlecouk06-21&linkCode=asn&creative=22206&creativeASIN=B002NX0ME6
[brand] => SanDisk
[condition] => new
[gtin] => 00619659059989
[gtins] => Array
(
[0] => 00619659059989
)
[mpns] => Array
(
[0] => SDMX18-008G-E46K
)
[inventories] => Array
(
[0] => Array
(
[channel] => online
[availability] => inStock
[price] => 46.95
[shipping] => 0
[currency] => GBP
)
)
[images] => Array
(
[0] => Array
(
[link] => http://ecx.images-amazon.com/images/I/419U6bYDF1L.jpg
[status] => available
)
)
)
)
I don't need all this data i just need 3-4 of the keys but how would i access them? How would i echo the value of say [title] from each array?
This should work:
foreach( $results as $result)
foreach( $result['product'] as $product)
echo $product['title'];
You could either loop through the array like pointed out above or possibly use array_walk_recursive like this:
$title_array = array();
array_walk_recursive($input_array, 'find_titles');
function find_titles($value, $key) {
global $title_array;
if ($key == 'title') {
$title_array[] = $value;
}
}
This might be a better solution if you you are not certain what the structure of the input array will be (i.e. how many levels deep the key you are looking for is nested).
To output the title of each product in $results:
foreach ($results as $result) {
echo $result['product']['title'];
}
Consider using array_walk_recursive
Working example
<?php
$a = array("hai", array("ha"=>1, "hai"=>2, array("a"=>1, "b"=>2)));
function test($item, $key)
{
echo "$key holds $item\n";
}
array_walk_recursive($a, 'test');
0 holds hai
ha holds 1
hai holds 2
a holds 1
b holds 2
If you are interested only in title
Consider using foreach
foreach($results['item'] as $result) {
echo $result['product']['title'];
}

Best way to insert an array element inside an array of arrays

I'm trying to insert an array element which contains an id for relational data inside an array save multiple records in CakePHP.
This is how the array appears:
[Venue] => Array (
[0] => Array (
[name] => Great mansion
[where] => New York
)
[1] => Array (
[name] => Diamond palace
[where] => London
)
[2] => Array (
[name] => Palazzo Falcone
[where] => Bologna
)
)
I would like to add the architect_id to every element of the array, so:
[Venue] => Array (
[0] => Array (
[name] => Great mansion
[where] => New York
[architect_id] => 33
)
[1] => Array (
[name] => Diamond palace
[where] => London
[architect_id] => 33
)
[2] => Array (
[name] => Palazzo Falcone
[where] => Bologna
[architect_id] => 33
)
)
I'm not sure if what I've wrote is optimized or it can be improved:
$tot = count($this->request->data['Venue']);
for ($i = 0; $i < $tot; $i ++) {
$this->request->data['Venue'][$i]['architect_id'] = $this->Architect->id;
}
$this->Venue->saveAll($this->request->data['Venue']);
The code works but is this a good way to do that?
Your solution is fine so far.
foreach ($this->request->data['Venue'] as &$venue) {
$venue['architect_id'] = $this->Architect->id;
}
Should work too. Decide yourself, which one you find more readable.

Categories