Renaming array keys that differ on each run - php

This is driving me mad.. I have a PHP script that returns an array in the form $key => $value and I want to rename the key so that I can display it in a table header. I saw there are several ways of doing this but I'm not sure they are what I need... Either that or I haven't understood the examples correctly which is the likely problem.
Basically my array keys differ each time I iterate over a foreach loop and also some can be blank. How can I get round this?
The first output might look like this:
'_can_chaccess' => false,
'_can_chown' => false,
'_can_delete' => false,
'_can_modify' => false,
'_can_read' => true,
'assigned_to_name_879' => 'Unassigned',
'id' => 1,
'type' => 'Private::Reporting::DataViewModel::DataView_223_42858',
'type_877' => 'Email',
The next run through, I might get this:
'_can_chaccess' => false,
'_can_chown' => false,
'_can_delete' => false,
'_can_modify' => false,
'_can_read' => true,
'assigned_to_name_793' => 'Consultants',
'id' => 1,
'object_reference_794' => 'CASE-1004',
'summary_795' => 'Deployment of New System for HQ (Project)',
'type' => 'Private::Reporting::DataViewModel::DataView_200_42858',
),
As you can see, some keys rename the same e.g. id, type. But the most important ones that I am interested in change each time e.g. Assigned To Name.
Any ideas?

Where do you receive your data from?
You can either somehow modify the source of your data, so if it were a query (what I do not assume here), you have the SELECT ... AS ... statement.
First you do need to know how to interpret the changing keys. If e.g. "assigned_to_name_879" and "assigned_to_name_793" is the same field, you can define a canonical function, which mapps both inputs to a unique output.
The output of the cannonical function and as well the other array keys can serve as keys for an additional array, which contains the table headers of your output.
So your current array is the value's array, and by hand you define a header's array:
array(
'assigned_to_name_879' => 'Name assignment'
);
This dynamic way of storing the table headers in an array only makes sense if you are using the array twice. Otherwise you could simply write the header in the html-code which you do output.

I've managed to figure it out using the below:
$mappings_array = array();
foreach ($report['data'][0] as $key => $value) {
$workbooks->log('Old Key', $key);
preg_match_all('([^_\d]+)', $key, $new_key);
$workbooks->log('New Key', $new_key);
$str = implode(" ", $new_key[0]);
$capitalised = ucwords($str);
array_push($mappings_array,$capitalised);
}
Maybe it's not the best solution but it works :) I get the following output:
> New array: «array (
0 => 'Can Chaccess',
1 => 'Can Chown',
2 => 'Can Delete',
3 => 'Can Modify',
4 => 'Can Read',
5 => 'Id',
6 => 'Total Type',
7 => 'Type',
8 => 'Type',
)

Related

Simpliest way to build a multi-dimensional array with SQL result?

I am currently building a web planning and I want to show some data in the period display.
I have a PHP file where I create my SQL request over ~13 tables and fetch all results (I use PDO::FETCH_ASSOC), then I have to loop over my result to build the array I want.
The problem is I need to build a complicated array with lot of data. Here is the kind of result I want to achieve :
$result = array(
$place_1 => array(
'data_place' => array(
'id' => ...,
'name' => ...,
// etc.
),
'data_target' => array(
$target_type_1 => array(
$name_1 => ...,
$name_2 => ...,
// etc.
),
$target_type_2 => array ( ... ),
// etc.
),
'data_isOpen' => array(
$day_1 => array(
$hour_begin => ...,
$hour_end => ...
),
$day_2 => array ( ... ),
// etc.
),
'data_box' => array(
// same kind of stuff with more dimension
)
),
...
$place_n = array(
// same
)
);
When I execute my request, I get something like 3000 array with all the data I need, but I only have 29 places in database so there is a lot of repetition...
$result = array(
0 => array(
"id" => ...,
"name" => ...,
// the list of all fields I need in my big array
),
...
n => array(
// same
)
);
I almost manage to achieve the result I want with some "foreach" and headaches but here is my question :
Is it possible to build a SQL request and fetch the result as I want? I mean, can I group all the result by "id_place" for example but wihtout lost information? And if it's possible, can we do it multiple time?
The idea is to get a result with one array for every place (so 29 and not 3000), then for every "place array", group for example the "hour_begin" and "hour_end" by "opening_day", etc...
Sorry if it's a duplicate, I didn't saw any positive anwser to my question so I try again !

using in_array() with keys and values in arrays?

Let's say I have an array
$array = array(
'username' => "username",
'location' => "location",
'other' => "other");
This array can hold data for many users, so there could be different values for each 'username', 'location', and 'other' fields. How can I use in_array() or another function to determine if a specific username exists in the array already? Because what if a user has a username like "nyc" and a location of "nyc" and I do
in_array("nyc", $array);
How exactly should something like this be approached?
Thank you.
To achieve something that I think is what you want, you can make an array of associative arrays that have the same keys.
<?php
// This syntax will work only on PHP 5.4
$a=[["name"=>"john","age"=>25],["name"=>"philip","age"=>110]];
print_r(array_filter($a, function($item) {return $item["name"] === "john"; }));
?>
Outputs:
Array
(
[0] => Array
(
[name] => john
[age] => 25
)
)
If you just wanted to know if a person named John was in the list, you can just use sizeof/count on the returned array.
This will allow you to have any number of duplicates, and you don't need to specify any keys. Check out the functions: array_filter, array_reduce, array_map. With all of these, you can process your list using closures like in my example above.
Instead of using associative arrays in your array, you could have objects too. Objects are more heavyweight, and need initialization and stuff, so it is grotesque for using them for tiny static (hardcoded) lists. But they may come handy when your data structures grow and you want to make sure every list item has a certain property (the constructor of the class could ensure that everything is initialized). But the good thing is that filter, reduce and map would still work. The "$item" would then be your object.
$users = array( 'user_id' => array('username' => "username",
'location' => "location",
'other' => "other");
user_id is their NUMBER user_id
So you then call $users['####']['username'];
IE:
$users = array( '1' => array('username' => 'Jim',
'location' => 'Florida',
'other' => "other"),
'2' => array('username' => 'Jane',
'location' => 'Maryland',
'other' => "Grapes"));
Then use array_keys() to search for their user_id

PHP / Mongo: how do you update nested data?

I've been playing around with Mongo for about a week now and I still can't work out how to modify nested arrays in Mongo with php.
So here is a sample document...
array (
'_id' => new MongoId("4cb30f560107ae9813000000"),
'email' => 'mo#maurice-campobasso.com',
'firstname' => 'Maurice',
'lastname' => 'Campobasso',
'password' => 'GOD',
'productions' =>
array (
0 =>
array (
'title' => 'a',
'date' => '1286811330.899',
),
1 =>
array (
'title' => 'b',
'date' => '1286811341.183',
),
2 =>
array (
'title' => 'c',
'date' => '1286811350.267',
),
3 =>
array (
'title' => 'd',
'date' => '1286811356.05',
),
),
)
What I wan't to do is delete an array inside the productions array, but I can't work out how. I've been playing with 'update('$pull' => ...etc)' but I haven't been able to make it work.
OK, there are a few ways to do this. In your case, I would do something like
mymongoobject.update( $unset : { "productions.2" : 1 } }
That's basically saying to unset the ".2" element of productions. Some docs here.
Now $pull should also work, but it's a little tougher because "productions" is actually an array of arrays (or objects with sub-objects). So you'd have to match arrays exactly:
mymongoobject.update( $pull : { "productions" : {'title':'d', 'date':'1286811356.05'} }
In the case above, the unset is probably the easiest option (though it will leave a "hole" in the array)
That is actually very easy, unlike traditional sql stuff you just modify the whole data and pass it back.
$cursor = $mongo->yourDB->yourCollection->findOne("_id",4cb30f560107ae9813000000);
//let's remove last item on productions
array_splice($cursor["productions"],2);
//and update the mongo document
echo $mongo->yourDB->yourCollection->update($cursor);
//it echoes 1 if successful
hope it helps.

Mongodb and PHP: how to query nested arrays without using the key name

I'm probably missing something simple here but I can't seem to find a way to build a query that will allow me to update a match in a group of nested values.
I have a document like this for a blog app I've been working on (currently uses MySQL):
array (
'_id' => new MongoId("4bc8dcee8ba936a8101a0000"),
'created' => '20100418-201312 +0000',
'post-title' => 'Some Post Title',
'post-body' => 'Blah Blah Blah Blah.',
'post-blog-name' => 'default',
'post-comments' =>
array (
0 =>
array (
'comment-title' => 'Test1',
'comment-body' => 'asdf1',
'created' => '20100418-214512 +0000',
'owner' => 'User1',
),
1 =>
array (
'comment-title' => 'Test2',
'comment-body' => 'asdf2',
'created' => '20100418-214512 +0000',
'owner' => 'User2',
),
),
'owner' => 'zach',
'updated' => '20100418-201312 +0000',
)
I'd like to be able to build a query that can search 'comment-title' for a match and then allow me to update/change/delete data as needed.
Obviously I can perform an update using a query which includes the key value. Something like this works:
$collection->update(
array("post-comments.0.comment-title" => $_POST['comment-title']),
array('$set' => array('entries.0' => array('comment-title' => $_POST['comment-title'], 'comment-body' => $_POST['comment-body'], 'owner' => $_SESSION['username'], 'updated' => gmdate('Ymd\-His O')))));
But I expect I'm missing something that would allow me to leave out the key and still be able to match one of the nested arrays based on a value (in this example the 'comment-title').
Anyway, sorry, this probably isn't the best example and I probably will end up using the keys in comments to identify them (comment #) but since nesting and creating rather complex objects seem to be a few of Mongodbs strong points I'm just hoping someone can point out what it is I might be missing.
A query to remove or update all comments by a specific user (say a user the blog author just black-listed) might be a better example. I'm not sure how I'd do this short of pulling out the entire document and then iterating through the nested arrays using PHP.
try ... notice I removed the "key"
$collection->update(array("post-comments.comment-title" ...
Cheers!

Retrieve first key in multi-dimensional array using PHP

I would like to retrieve the first key from this multi-dimensional array.
Array
(
[User] => Array
(
[id] => 2
[firstname] => first
[lastname] => last
[phone] => 123-1456
[email] =>
[website] =>
[group_id] => 1
[company_id] => 1
)
)
This array is stored in $this->data.
Right now I am using key($this->data) which retrieves 'User' as it should but this doesn't feel like the correct way to reach the result.
Are there any other ways to retrieve this result?
Thanks
There are other ways of doing it but nothing as quick and as short as using key(). Every other usage is for getting all keys. For example, all of these will return the first key in an array:
$keys=array_keys($this->data);
echo $keys[0]; //prints first key
foreach ($this->data as $key => $value)
{
echo $key;
break;
}
As you can see both are sloppy.
If you want a oneliner, but you want to protect yourself from accidentally getting the wrong key if the iterator is not on the first element, try this:
reset($this->data);
reset():
reset() rewinds array 's internal
pointer to the first element and
returns the value of the first array
element.
But what you're doing looks fine to me. There is a function that does exactly what you want in one line; what else could you want?
Use this (PHP 5.5+):
echo reset(array_column($this->data, 'id'));
I had a similar problem to solve and was pleased to find this post. However, the solutions provided only works for 2 levels and do not work for a multi-dimensional array with any number of levels. I needed a solution that could work for an array with any dimension and could find the first keys of each level.
After a bit of work I found a solution that may be useful to someone else and therefore I included my solution as part of this post.
Here is a sample start array:
$myArray = array(
'referrer' => array(
'week' => array(
'201901' => array(
'Internal' => array(
'page' => array(
'number' => 201,
'visits' => 5
)
),
'External' => array(
'page' => array(
'number' => 121,
'visits' => 1
)
),
),
'201902' => array(
'Social' => array(
'page' => array(
'number' => 921,
'visits' => 100
)
),
'External' => array(
'page' => array(
'number' => 88,
'visits' => 4
)
),
)
)
)
);
As this function needs to display all the fist keys whatever the dimension of the array, this suggested a recursive function and my function looks like this:
function getFirstKeys($arr){
$keys = '';
reset($arr);
$key = key($arr);
$arr1 = $arr[$key];
if (is_array($arr1)){
$keys .= $key . '|'. getFirstKeys($arr1);
} else {
$keys = $key;
}
return $keys;
}
When the function is called using the code:
$xx = getFirstKeys($myArray);
echo '<h4>Get First Keys</h4>';
echo '<li>The keys are: '.$xx.'</li>';
the output is:
Get First Keys
The keys are: referrer|week|201901|Internal|page|number
I hope this saves someone a bit of time should they encounter a similar problem.

Categories