automatically increment array dimension [duplicate] - php

This question already has answers here:
Using a string path to set nested array data [duplicate]
(8 answers)
Closed 3 years ago.
I am trying to find a way to create an array of directories. But as we all know directories can have many subDirs and those subDirs can have more subDir and so on and on. The directories length are unknown as it can change.
Say I have a directory as www/webs/apps/pics and another www/webs/test.
The idea would be to have an array such as: (yes the below is json, i just converted it in my php demonstration because i find it easier to read)
{
"www": {
"webs": {
"apps": {
"pics": "Im Here"
}
},
"test": "im Here too"
}
}
There is no relation from the above output to the below code. The below code is here just to give an idea what I need.
$exploedDir = explode("/", $unsortedDir);
foreach ($exploedDir as $dir){
$this->allDirectiroesFound[$dir] = $dir;
}
How can I make $this->allDirectiroesFound has as many dimensions as it is needed without knowing the length of the directory, I cant hard code $this->allDirectiroesFound[][][][][][] it as next time around the array length might be [][][].

You can just reverse each of the path arrays and then go on creating the Keys from the last directory.
$paths = [
'www/webs/apps/pics',
'www/webs/test',
];
$finalArray = [];
foreach($paths as $path){
$revArr = array_reverse(explode("/", $path)); // This is the trick. Start to build from inside out.
$pathArray = [];
foreach($revArr as $key){
$tempBucket = $pathArray;
$pathArray = []; // Create fresh empty array to hold the
$pathArray[$key] = $tempBucket;
}
$finalArray = array_merge_recursive($pathArray, $finalArray); // Recursively Merge the array into the main array
}
echo "<pre>";
print_r(json_encode($finalArray, JSON_PRETTY_PRINT));
echo "</pre>";
DEMO

I guess you would need to use arrays of arrays to solve this.
e.g.
var directories = ["base"];
var subdir1 = ["subdir1"];
var subsubdir1 = ["subsubdir1"];
var subsubdir1 = ["subsubdir2"];
subdir.push(subsubdir1);
subdir.push(subsubdir2);
directories.push(subdir1);
so this forms a base->subdir1->[subsubdir1, subsubdir2] structure. The complication comes in ensuring that every 'push' you perform is an array to allow adjacent siblings to exist for that particular sub-directory. That and keeping track of the directory structure

Related

PHP Merge json files [duplicate]

This question already has answers here:
Merging two json in PHP
(4 answers)
Closed 2 years ago.
I have 2 json file each file contain 500 arrays. i need to merge 2 files in 1 file so the result will be 1000 arrays. I have found code from stackoverflow but its not working its just showing me the file 1 data.
<?php
$a = file_get_contents ("cache.json");
$b = file_get_contents ("cache2.json");
$r = [];
foreach(json_decode($a, true) as $key => $array){
$r[$key] = array_merge(json_decode($b, true)[$key],$array);
}
echo count($r);
?>
The json data look like this
$a = '[{"COLUMN_NAME":"ORDER_NO","COLUMN_TITLE":"Order Number"},{"COLUMN_NAME":"CUSTOMER_NO","COLUMN_TITLE":"Customer Number"}]';
$b = '[{"COLUMN_NAME":"ORDER_NO","DEFAULT_VALUE":"1521"},{"COLUMN_NAME":"CUSTOMER_NO","DEFAULT_VALUEE":"C1435"}]';
Try array_merge with json_decode
$r = array_merge(json_decode($a,true), json_decode($b,true));
echo json_encode($r);
Working example : https://3v4l.org/J6iW3
Alternative solution, without decoding:
function concatJsonArrays(...$arrays) {
$result = [];
foreach ($arrays as $array) {
$result[] = substr($array, 1, strlen($array) - 2);
}
return "[".implode(',', $result)."]";
}
// print result aray
echo concatJsonArrays($a, $b);
This solution must be better, if you have big json data or deep objects in json.
You can use array merge but I would suggest first ensuring the JSON code is valid AND the files exist before assuming json_decode will return an array. Otherwise, if you merge NULL or FALSE with an array, you end up with FALSE as the final result.
Imagine the first cache file exists, and the other one doesn't or one of them is broken and contains broken encoded JSON data.
With checks, at least you know you will always get an array with as much of the valid array data as possible or know when to report errors and one which file in one of the stages.
$data = Array();
foreach(Array("cache.json","cache2.json") as $f){
$dc = Array();
if($fc = file_get_contents($f)){
if($dc = json_decode($fc,true)){
$data = empty($data)?$dc:array_merge($data,$dc);
}
}
}
echo json_encode($data);

Get difference in an array in PHP

In my scenario a paintings list is located in the column in json format. Paintings list contains file name, painting name and view count. I want to delete a painting in the list. But I did not manage. Here is my codes:
$paintings = '[["24ef9-70076-4358c-48386.jpg","La Donna Gravida","649"],["a7972-065a9-4c0f9-723d1.jpg","Madonna and Child with the Book","1254"],["b054c-df208-0f600-e884e.jpg","Madonna del Granduca","1457"]]';
$painting = 'a7972-065a9-4c0f9-723d1.jpg';
$difference = array_diff((array)json_decode($paintings), (array)$painting);
echo json_encode(array_values($difference));
I am trying to reach the following conclusion: [["24ef9-70076-4358c-48386.jpg","La Donna Gravida","649"],["b054c-df208-0f600-e884e.jpg","Madonna del Granduca","1457"]] But I get error like this: Notice: Array to string conversion in... Could you help me?
You do not have objects with keys in the json string, so the array you create by decoding it will not be associative with keys. One of the possible ways to solve your problem is shown below (straight forward one).
$out = array();
foreach(json_decode($paintings, true) as $p)
if (!in_array($painting, $p))
$out[] = $p;
echo json_encode(array_values($out));
Another way
$out = array_filter(json_decode($paintings, true), function($el) use($painting) {
return !in_array($painting, $el);
});
echo json_encode(array_values($out));
The reason is because ["a7972-065a9-4c0f9-723d1.jpg","Madonna and Child with the Book","1254"] is not an element with key or value a7972-065a9-4c0f9-723d1.jpg - it is another array and you have to check either the existence of the value in the whole sub-array or just its first element. In that case !in_array($painting, $el) can be replaced by $painting != $el[0]

WordPress, MySQL, php - query results not acting as a string [duplicate]

This question already has answers here:
How to modify an array's values by a foreach loop?
(2 answers)
Closed 8 years ago.
This is driving me nuts. I've searched for solutions but can't figure out what's wrong.
The situation... I have an SQL query running in WordPress, as follows:
SELECT distinct guid
FROM $wpdb->posts
WHERE post_status = 'inherit'
AND guid is not null
Dead simple. It returns a single column which contains a list of all the attachment media files currently stored on the system (well, not all of them, but it'll do as an explanation).
In a WP plugin function, I run the query:
$media_library_files = $wpdb->get_col($get_all_media,0);
That returns an array (I don't want an object) with values like:
[0] => http://mysitename.com/wp-content/uploads/2013/05/thumb_littlefile_blah.jpg
Then I want to process each one so that there's just the filename left. The problem is that, when I run a str_replace or pretty much any other string function on the contents, it doesn't work. For example:
$horrid_bit = 'http://mysitename.com/wp-content/uploads/2013/05/';
foreach($media_library_files as $item) {
$item = str_replace($horrid_bit,'',$item);
}
When I print_r the array after that, there's no visible change - every line is exactly the same as it was before.
I've tried using a (string) to cast $item, I've tried defining variables to do that, then working the str_replace on them, I've tried... loads of different things.
I have a feeling I'm missing something really simple, but I just can't see it. Is it because the column is varchar in the original table? Or something else?
Any help appreciated. Thanks!
PHP is not my 'native languague', but it seems like you're not modifying the values in the array. Did you try to put the modified string items (=minus the path) in a new array and use that one?
$horrid_bit = 'http://mysitename.com/wp-content/uploads/2013/05/';
$new_array = array();
foreach($media_library_files as $item) {
$new_item = str_replace($horrid_bit,'',$item);
$new_array.push($new_item);
}
//...use the items in the $new_array
Also, you might wanna just read the whole path string as an array (split on '/')and take the last element to get to the file.
$horrid_bit = 'http://mysitename.com/wp-content/uploads/2013/05/';
foreach($media_library_files as $key => $value) {
$media_library_files[$key] = str_replace($horrid_bit,'', $value);
}
But as Michael pointed out if you are not doing it this way for a specific purpose using basename would be better here, so you don't have to worry about the folder changing each month/year.
foreach($media_library_files as $key => $value) {
$media_library_files[$key] = basename($value);
}
You are not actually changing the value of $item in your array, you are instead creating a new variable, which is then overwritten every time your loop iterates.
It's also a good idea to check that the array is not empty before attempting a foreach() loop on it.
Finally, I've replaced str_replace() with basename() (as suggested in the comments under your question by #MichaelBerkowski).
if(!empty($media_library_files)) : foreach($media_library_files as $item) :
$media_library_files[$item] = basename($item);
endforeach;
endif;
str_replace() can handle arrays. No need for your foreach loop.
$horrid_bit = 'http://mysitename.com/wp-content/uploads/2013/05/';
$media_library_files = str_replace( $horrid_bit,'',$media_library_files );
On the other hand, since it seems you want to remove the path and get only the filename:
foreach($media_library_files as $key => $item) {
$media_library_files[$key] = basename($item);
}
This will change all entries to the filename only. The way you have it now you will have to change the $horrid_bit every month since the uploads are organized in year/month/ folders.

Problem with associative arrays

I have always sucked at complex arrays there must be something in my brain preventing me from ever understanding them. I will try to make this example really simple so we will not go off topic. I use this code to use numbers to represent each file name:
$mod_nums = array('1' => $input_zip_path . '01_mod_1.0.2.zip',
'2' => $input_zip_path . '02_mod_1.0.1.zip',
);
So when I use $mod_nums['01'] it will display the path to that file. I have an array from the script that put these $mod_nums values into an array like so:
$files_to_zip = array(
$mod_nums['1'],
$mod_nums['2']
);
That worked fine. Now I wanted to add a $_POST value so that I can enter numbers like 1,2 and other numbers that I add to the $mod_nums array later like 1,3,6,12 for example. So I used an explode for those posted values:
$explode_mods = explode(",", trim($_POST['mods']));
Now for the big question that is racking my brain and spent hours on and cannot get it to work.... I need for $files_to_zip to still be in an array and display the posted values of $mod_nums. So it would be like:
$files_to_zip = array( HAVE $_POSTED VALUES IN HERE );
I hope that makes sense. I need $files_to_zip to remain in array format, grab the file path to the zip files from the $mod_nums array, and display it all correctly so it would dynamically output:
$files_to_zip = array('01_mod_1.0.2.zip', '02_mod_1.0.1.zip');
so posted numbers will appear in an array format for the $files_to_zip variable. Make sense? In short I need an array to have dynamic values. Thanks :)
EDIT
Phew I figured it out myself from memory when I worked on something similar many years ago. This looks tough but it isn't. I had to use a foreach and assign the variable into an array like so:
$blah = array();
foreach ($explode_mods as $value)
{
$blah[] = $mod_nums[$value];
}
then I just assigned $files_to_zip to $blah:
$files_to_zip = $blah;
works perfectly :) I just forgot how to dynamically assign values into an array.
// filenames array
$mod_nums = array('1' => $input_zip_path . '01_mod_1.0.2.zip',
'2' => $input_zip_path . '02_mod_1.0.1.zip',
);
// mod_num keys
$explode_mods = explode(',', trim($_POST['mods']));
// array to hold filenames
$files_to_zip = array();
// loop over all the mod_num keys submitted via POST
foreach($explode_mods as $key){
// save the filename to the corresponding array
$files_to_zip[] = $mod_nums[$key];
}
maybe i havn't understood you right, but won't this just be a simple foreach-loop to add the entrys to $files_to_zip like this:
$explode_mods = explode(",", trim($_POST['mods']));
foreach($explode_mods as $k){
$files_to_zip[] = $mod_nums[$k];
}

Duplicate array but maintain pointer links

Suppose I have an array of nodes (objects). I need to create a duplicate of this array that I can modify without affecting the source array. But changing the nodes will affect the source nodes. Basically maintaining pointers to the objects instead of duplicating their values.
// node(x, y)
$array[0] = new node(15, 10);
$array[1] = new node(30, -10);
$array[2] = new node(-2, 49);
// Some sort of copy system
$array2 = $array;
// Just to show modification to the array doesn't affect the source array
array_pop($array2);
if (count($array) == count($array2))
echo "Fail";
// Changing the node value should affect the source array
$array2[0]->x = 30;
if ($array2[0]->x == $array[0]->x)
echo "Goal";
What would be the best way to do this?
If you use PHP 5:
Have you run your code? It is already working, no need to change anything. I get:
Goal
when I run it.
Most likely this is because the values of $array are already references.
Read also this question. Although he OP wanted to achieve the opposite, it could be helpful to understand how array copying works in PHP.
Update:
This behaviour, when copying arrays with objects, the reference to the object is copied instead the object itself, was reported as a bug. But no new information on this yet.
If you use PHP 4:
(Why do you still use it?)
You have to do something like:
$array2 = array();
for($i = 0; $i<count($array); $i++) {
$array2[$i] = &$array[$i];
}
it is some time that I don' write PHP code, but does the code
// Some sort of copy system
$array2 = $array;
actually work?
Don't you have to copy each element of the array in a new one?

Categories