How to print complex multidimensional associative array in an table (PHP) - php

I want to be able to display the multidimensional associative array in a table. The arrays are created by Solarium API which is used for debugging any indexing issues. Each array has different number of arrays and keys.
I want it keep it in a way that it works with any number or arrays and keys. I started with using a foreach loop but I'm stuck at this point. How would I go about doing this?
Code I have so far:
foreach ($metadatas as $metadata) {
foreach($metadata as $type => $data) {
echo '<tr>';
echo '<td>'.$type.'</td>';
echo '<td>'.$data.'</td>';
echo '</tr>';
}
}
This is the array I get using print_r():
Solarium\QueryType\Extract\Query Object
(
[options:protected] => Array
(
[handler] => update/extract
[resultclass] => Solarium\QueryType\Extract\Result
[documentclass] => Solarium\QueryType\Update\Query\Document\Document
[omitheader] =>
[extractonly] =>
[uprefix] => ignored_
[commit] => 1
[file] => http://url.com/branch/files/2015/03/Client-Feedback-Form.doc
[document] => Solarium\QueryType\Update\Query\Document\Document Object
(
[boost:protected] =>
[modifiers:protected] => Array
(
)
[key:protected] =>
[fieldBoosts:protected] => Array
(
[id] =>
[site] =>
[description] =>
[url] =>
[title] =>
)
[version:protected] =>
[helper:protected] => Solarium\Core\Query\Helper Object
(
[placeHolderPattern:protected] => /%(L|P|T|)([0-9]+)%/i
[assembleParts:protected] =>
[derefencedParamsLastKey:protected] => 0
[query:protected] => Solarium\QueryType\Update\Query\Document\Document Object
*RECURSION*
)
[filterControlCharacters:protected] => 1
[fields:protected] => Array
(
[id] => 227-7653
[site] => Branch Name
[description] =>
[url] => http://url.ca/branch/files/2015/03/Client-Feedback-Form.doc
[title] => Client Feedback Form
)
)
)
[fieldMappings:protected] => Array
(
[content_type] => type
[author] => authors
[last_modified] => lastModifiedDate
[creation_date] => creationDate
[content] => content
)
[helper:protected] =>
[params:protected] => Array
(
)
)

I need more fake internet points to comment. So instead you get my poor answer. I'd try some sort of recursive function calling.
function someFunction($table , $array){
foreach($array as $key => $value){
if(is_array($value)){
someFunction(&$table, $value)
}
else {
//Add to your existing $table
}
}
return $table;
}
$table = someFunction("" , array());
obviously this is super simplistic view. But the idea is to keep passing your table deeper and deeper into the array. And eventually it will fall back out as you stop running into new arrays. I did something similar a while back passing around a DOMDocument() to build a super complex XML.
But this is only really useful when you don't know the possible size or depth of an array. If your array has keys, even if it's multidimensional, that you know will or won't exist and how deep they go. It's probably better to follow the answer in your comments and just build a nice HTML page.
Good luck.

As you can see from the first line of your output, it is not an array, but an OBJECT! And as you see in [options:protected] , it is protected variable, so you cannot access it from external foreach loop.
What you can do, is to declare a loop function inside that class:
class Query{
....
....
public function iterate(){
foreach ($this->options as $metadata) {
foreach($metadata as $type => $data) {
echo '<tr>';
echo '<td>'.$type.'</td>';
echo '<td>'.$data.'</td>';
echo '</tr>';
}
}
}
}
And then call it outside the class:
$object->iterate();
You can read more about this here: http://php.net/manual/en/language.oop5.iterations.php

Related

PHP - Accessing data within array

Can't seem to work out how to access data within an array that has other arrays within it.
My array looks like:
Array
(
[0] => Array
(
[_id] => 28
[serv_image] =>
[serv_name] => My Service
[slug] => my-service
[is_featured] =>
[_blocks] => Array
(
[0] => Array
(
[anchor_heading] => Mats Heading
[_block_type] => anchorHeading
[_block_id] => pe8t69
[_block_index] => 0
)
[1] => Array
(
[anchor_heading] => Another anchored heading
[_block_type] => anchorHeading
[_block_id] => pea49u
[_block_index] => 1
)
)
[_page] => *
[_pageID] => 1
[_sortvalue] => 1003
)
)
So far I've tried this without success:
foreach($services as $service) {
print_r($service['_blocks']['anchor_heading']);
}
This results in undefined index on anchor_heading.
UPDATE
I will have an unknown amount of these that I need to group together into a variable. How can I ensure I'm grabbing them all, no matter how many other times it's been entered?
You might use 2 times a foreach and echo the value of anchor_heading:
foreach($services as $service) {
foreach ($service["_blocks"] as $block) {
echo $block["anchor_heading"];
}
}
You have an array for each _block .. so you need an indexed access .. (or an inner iteration)
foreach($services as $service) {
print_r($service['_blocks'][0]['anchor_heading']);
print_r($service['_blocks'][1]['anchor_heading']);
}
(or an inner iteration)
foreach($services as $service) {
$blocks = $service['_blocks'];
foreach( $blocks as $block) {
print_r($block['anchor_heading']);
}
}
You can use the following to access the data within your array in a for loop:
print($service['_blocks'][0]['anchor_heading']);

Syntax for reading an array in php

I have an array, stored in $array, that with
print "<pre>";
print_r($array);
print "</pre>";
gives an output like this:
Array
(
[device] => Array
(
[0] => Array
(
[#attributes] => Array
(
[name] => Low volt light
[id] => 10
[type] => Z-Wave Switch Multilevel
[value] => 0
[address] => 00016922-018
[code] =>
[canDim] => True
[lastChange] => 26-07-2014 17:31:33
[firstLocation] => Kitchen
[secondLocation] => Main
)
)
[1] => Array
(
[#attributes] => Array
(
[name] => Light
[id] => 11
[type] => Z-Wave Switch Multilevel
[value] => 99
[address] => 00016922-019
[code] =>
[canDim] => True
[lastChange] => 31-07-2014 20:01:05
[firstLocation] => Bedroom
[secondLocation] => Main
)
)
I cannot find my way to access/display for example the value (in this case 0) of device with [id]=>10. What syntax would be the right one in php?
There's not an easy way to do this, without looping through the array.
e.g.
foreach ($array['devices'] as $device) {
if ($device['#attributes']['id'] === $idBeingSearchedFor) {
// Do something with $device.
}
}
Due to the #attributes array key, I'm guessing that this came from XML at some point: You might consider using Simple XML to parse it instead, as you could potentially use XPath then, which does support this type of access.
Alternatively again, you could reformat the array so it could be easily accessed by ID.
For example:
$formattedArray = array();
foreach ($array['devices'] as $device) {
$id = $device['#attributes']['id'];
$formattedArray[$id] = $device;
}
You could then access the device by its ID as follows:
$device = $formattedArray[$idBeingSearchedFor];
You could do it like that:
$id = 10;
$device = array();
foreach($array['device'] as $devices) {
if($devices['#attributes']['id'] == $id) {
$device = $devices['#attributes'];
break;
}
}
echo $device['value'];
Looks like SimpleXML, and if that is the case then those arrays are actually objects that, when put through print_r, look just like arrays. To access them, do the following:
Get straight to the data:
$name = $array->device[0]->attributes()->name;
Or loop through each of the attributes in the first device:
foreach ($array->device[0]->attributes() as $key => $value) {
// Do something with the data. $key is the name of the
// attribute, and then you have the $value.
}
Or you could loop through all the devices:
foreach ($array->device as $device) {
foreach ($device->attributes() as $key => $value) {
// Do something
}
}
It's simple ... try below...
print $array['device'][0]['#attributes']['id'];
or
print $array['device']['0']['#attributes']['id'];

Extracting Data from Multidimensional Array

I'm working with the S3 library found here: http://undesigned.org.za/2007/10/22/amazon-s3-php-class/
It works great, but I'm having a tough time extracting the data I need from the returned array results. I'm grabbing the bucket contents, and it returns something like this:
Array (
[sample_mpeg4.mp4] => Array (
[name] => sample_mpeg4.mp4
[time] => 1378922417
[size] => 245779
[hash] => dc77a8de8c091c19d86df74eb7
)
[steve.jpg] => Array (
[name] => steve.jpg
[time] => 1381270899
[size] => 61109
[hash] => a008368bf58515775c45e75c54
)
[stev-small-photo1.png] => Array (
[name] => stev-small-photo1.png
[time] => 1381270891
[size] => 680353
[hash] => ddcb22a103d4fa8360083ad70a
)
)
Ok, cool. I'm querying and matching the key to pull out specific info on that particular piece of media. My code for that looks like this:
$searchVar = "steve.jpg";
$s3 = new S3(awsAccessKey, awsSecretKey);
$bucket_contents = $s3->getBucket("uploads.bucket.com");
//fetch array of current files
$searchAssetsBucket = array_keys($bucket_contents);
foreach ($searchAssetsBucket as $value) {
if($value == $searchVar) {
echo $value['time'];
}
}
if(empty($returnValue)) {
$returnValue = "Sorry no results for <b>$searchVar</b>.";
}
This doesn't work for me. What I'm really trying to do is get the code to return the name/time/size/hash vars from the [steve.jpg] array once it's been matched. I'm not sure what I'm doing wrong here, but this code simply returns "s".
Does anyone have any ideas? I'm truly at a lose here...
I would do something like this:
$myArray=$yourOriginalS3Array;
$searchVar='Steve.jpg';
// set up default/blank data in $matchedArr
foreach ($myArray as $key => $val)
{
if($key == $searchVar) {
$matchedArr=$val;
}
}
echo "The name is ".$matchedArr['name']." and the size is ".$matchedArr['size']."<br>";
This way, you are checking the keys of your original array, and if matched, returning an array that matches the second level of the original array which can be easily accessed in your code.

CakePHP Model Query Return Data Formating

I'm looking for a way to make it so cake returns all database data in the same format/structure... Currently it returns two different types of format depending on the relationship.
If a model 'B' is associated with the current model 'A' being queried it will then place model associations for 'B' underneath it as you can see in [User] below. I want it so that all queries use that structure.
example:
$this->find('all', ....
returns:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
)
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
I want this to look like:
Array
(
[0] => Array
(
[UserGroup] => Array
(
[id] => 53
[user_id] => 100003332014851
[media_id] =>
[name] => john
[description] => qwasdfad
[User] => Array
(
[id] => 100003332014851
[session_id] => ssm2qbrotmm13ho1ipm8ii2492
[username] =>
[password] => -1
[Planner] => Array
(
)
[Purchase] => Array
(
)
[Listing] => Array
(
)
)
)
)
)
In CakePHP, the find() method return data like your first format. But If you want to format like second one then you have to process it by hand (try to avoid this if possible)
$data = $this->find('all');
$assocs = Set::extract('/User', $data); // extracting all `User` array
foreach($assocs as $key => $assoc) {
unset($data[$key]['User']); // removing the associate `User` from `$data`
$data[$key]['UserGroup']['User'] = $assoc['User']; // adding associate under `UserGroup`
}
ended up doing this... it changes the output to what we need. The top level item does not have a header which is fine I just adjusted our scripts for that... maybe this will help somebody else if they need a custom idea
also no guarantee this covers all possible results but so far it works with all the queries we have.
class AppModel extends Model {
function afterFind($results, $primary) {
//if this is a primary, structure like a secondary so entire site is same format
if ($primary) {
$class = get_class($this);
//simple fix for primary
foreach ($results as $key => $result) {
$result = $this->formatData($result, $class);
$results[$key] = $result;
}
}
return $results;
}
function formatData($result, $class) {
$array = array();
if (isset($result[$class])) {
$array = $result[$class];
unset($result[$class]);
}
$array += $result;
return $array;
}
You can also use contain in this case along with find as UserGroup.User for your desired result

PHP Accessing named array elements issue

I have an array which is generated from an XML file and it shows me like below when printed with print_r
Array
(
[cxname] => Global CX 87 123
[ipaddress] => 66.240.55.87
[slots] => Array
(
[slot] => Array
(
[0] => Array
(
[slotno] => 1
[cardtype] => 0x24
[modelno] => OP3524J
[label1] => OP
[label2] => Module
[severity] => Minor
)
[1] => Array
(
[slotno] => 2
[cardtype] => 0x25
[modelno] => OP3524K
[label1] => OP
[label2] => Module
[severity] => Major
)
)
)
)
When I print like this, it shows nothing
echo $dataArray->cxname;
But following code works and prints "Global CX 87 123 "
echo $dataArray["cxname"];
How can I make it work as above example.
Just do this:
$dataArray = (object)$dataArray;
It'll convert the array in an stdClass object and allow you to use it that way. Please note that this will only convert the first level for the array. You'll have to create a function to recurse through the array if you want to access all levels that way. For example:
<?php
function arrayToObject($array) {
if(!is_array($array)) {
return $array;
}
$object = new stdClass();
if (is_array($array) && count($array) > 0) {
foreach ($array as $name=>$value) {
$name = strtolower(trim($name));
if (!empty($name)) {
$object->$name = arrayToObject($value);
}
}
return $object;
}
else {
return FALSE;
}
}
For more information, have a look at http://www.richardcastera.com/blog/php-convert-array-to-object-with-stdclass. To find out about typecasting, you can also read http://www.php.net/manual/en/language.types.object.php#language.types.object.casting.
This:
echo $dataArray["cxname"];
is the way you access array elements. But this:
echo $dataArray->cxname;
is the way, you access class members.
If you want to access the data as class members, you have to use a xml parser which returns classes (or objects), not arrays.
If you have got the XML string, you can parse it into an object by using simplexml_load_string().

Categories