I am trying to get multi-dimensional array for directories formatted as below :
[
{
"text": "another_folder",
"href": "gui\/default\/uploads\/another_folder",
"depth": 0
},
{
"text": "subfold",
"href": "gui\/default\/uploads\/subfold",
"depth": 0,
"nodes": {
"text": "sub-subfold",
"href": "gui\/default\/uploads\/subfold\/sub-subfold",
"depth": 1,
}
}
]
I want to use RecursiveIterators. What I have done so far is I am getting all directories listed in given path. I need to go inside to children which is where I stacked.
public function list_folders($folder_path='') {
if(!$folder_path) $folder_path = $this->upl_path;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($folder_path),
RecursiveIteratorIterator::SELF_FIRST);
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
$r = array();
$counter = 0
foreach ($iterator as $splFileInfo) {
if($splFileInfo->isDir()) {
$r[$counter] = array(
'text' => $splFileInfo->getFilename(),
'href' => str_replace('\\','/',$splFileInfo->getPathname())
);
if(How to check if it has children) {
$result[$counter] += array('nodes'=> CALL RECURSIVE HERE ? );
}
$counter++;
}
echo json_encode($r,JSON_PRETTY_PRINT);
}
I'd use any idea or help gladly.
Your code was almost functional, but it was missing a few key points. I adapted your code so that it works, and added some comments that I hope will help you understand what you were missing:
class FolderListing
{
public function list_folders($folder_path = '', $depth = 0)
{
if (!$folder_path) $folder_path = $this->upl_path;
$iterator = new IteratorIterator(new DirectoryIterator($folder_path));
$r = array();
foreach ($iterator as $splFileInfo) {
if ($splFileInfo->isDot()) {
continue;
}
// we need to do this for both folders and files
$info = array(
'text' => $splFileInfo->getFilename(),
'href' => str_replace('\\', '/', $splFileInfo->getPathname()),
'depth' => $depth
);
// is we have a directory, try and get its children
if ($splFileInfo->isDir()) {
// !!! I recommend to do an echo $splFileInfo->getPathname() here
// to see the order in which recursion works !!!
$nodes = $this->list_folders($splFileInfo->getPathname(), $depth + 1);
// only add the nodes if we have some
if (!empty($nodes)) {
$info['nodes'] = $nodes;
}
}
// add the info to the array. No need for a counter :)
$r[] = $info;
}
// the return is important to be able to build the multi dimensional array
return $r;
}
}
$test = new FolderListing();
$ret = $test->list_folders('./test'); // change this to whatever you want
var_dump($ret);
Good luck!
Related
How do i convert multidimensional array to file path.
I have this array :
$data = [
"users" => [
"joe" => [
"photos" => ["a.jpg","b.jpg"],
"files" => ["a.doc","b.doc"]
],
"annie" => [
"photos" => ["a.jpg","b.jpg"],
"files" => ["a.doc","b.doc"]
],
]
];
that i must convert to path example :
"users/joe/photos/a.jpg";
"users/joe/photos/b.jpg";
"users/joe/files/a.doc";
"users/joe/files/b.doc";
"users/annie/photos/a.jpg";
"users/annie/photos/b.jpg";
"users/annie/files/a.doc";
"users/annie/files/b.doc";
But i can't have the best result with this functions :
$path = "";
function iterate($data, $path)
{
echo "<br>";
foreach ($data as $key => $item){
if (is_array($item)){
$path .= $key.DIRECTORY_SEPARATOR;
iterate($item, $path);
}else{
echo $path.$item."<br>";
}
}
}
output :
users/joe/photos/a.jpg
users/joe/photos/b.jpg
users/joe/photos/files/a.doc
users/joe/photos/files/b.doc
users/joe/annie/photos/a.jpg
users/joe/annie/photos/b.jpg
users/joe/annie/photos/files/a.doc
users/joe/annie/photos/files/b.doc
Please help.
Thanks
You could make use of RecursiveIteratorIterator + RecursiveArrayIterator:
function computeFilePaths(array $fileTree): array
{
$filePaths = [];
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($fileTree));
foreach ($iterator as $fileName) {
for ($folders = [], $pos = 0, $depth = $iterator->getDepth(); $pos < $depth; $pos++) {
$folders[] = $iterator->getSubIterator($pos)->key();
}
$filePaths[] = implode('/', $folders) . '/' . $fileName;
}
return $filePaths;
}
print_r(computeFilePaths($yourArrayGoesHere));
I highly suggest this question's selected answer to understand how these iterators work.
i am making search engine using associated array now i want to make an associative array of a path in which i can get key as a document and value as a content.
below is my code
$file= 'D:\\data\\awd_1990_00\\';
$dictionary = array();
$docCount = array();
foreach($collection as $docID => $doc) {
$terms = explode(' ', $doc);
$docCount[$docID] = count($terms);
foreach($terms as $term) {
if(!isset($dictionary[$term])) {
$dictionary[$term] = array('df' => 0, 'postings' => array());
}
if(!isset($dictionary[$term]['postings'][$docID])) {
$dictionary[$term]['df']++;
$dictionary[$term]['postings'][$docID] = array('tf' => 0);
}
$dictionary[$term]['postings'][$docID]['tf']++;
}
}
return array('docCount' => $docCount, 'dictionary' => $dictionary);
}
?>
As you seen $collection is a associative array which i want to make kindly help me
Try to use this function:
<?php
function extractDocuments($p_dir) {
if(!is_dir($p_dir)) { //Check if $p_dir is a valid directory
//Throw exception or return FALSE
}
$path=$p_dir;
$dir=scandir($path); //Load directory contents
$collection=array();
foreach($dir as $file) { //Go through directory
if($file==".." || $file==".") {continue;} //Exclude parent directory and self
$collection[$file]=file_get_contents($path.$file); //Load file contents and save
}
return $collection;
}
?>
I'm trying to generate a JSON string that includes the id and url for all my categories, subcategories, and sub-subcategories. The code below only gets me as far as the top-level category, but I also need the second and third as well. My goal is to create a dynamically updating sitemap that decodes the string and makes an unordered list of every category level.
public function createCategoryTree() {
$_categories = Mage::getModel('catalog/category')->getCollection()->addAttributeToSelect('*')->addIsActiveFilter()->addLevelFilter(2)->addOrderField('position'); // load all categories
$arr = array();
if ($_categories){ // if there are categories
foreach ($_categories as $cat){
$cat_name = $cat->getName(); // name as key
if (strlen(stristr($cat_name,'default')) < 3) {
$cat_id = $cat->getId(); // id
$cat_url = $cat->getUrl(); // url
$arr[$cat_id] = array('title'=>$cat_name,'url'=>$cat_url);
}
}
}
print_r (json_encode($arr));
die;
}
I get something like this:
{
"637": {
"title": "bikes",
"url": "http:www.123.com/shop/bicycles "
}
}
But I want something like this:
{
"637": {
"title": "bikes",
"url": "http:www.123.com/shop/bicycles",
"children": {
"658": {
"title":"wheels",
"url":"http:www.123.com/shop/bicycles/wheels"
},
"489": {
"title": "pumps",
"url":"http:www.123.com/shop/bicycles/pumps"
}
}
}
Appreciate your time and help!
You can use some functionality provided by Mage_Catalog_Model_Resource_Category_Tree for this. See if this script works for you:
<?php
require_once('../app/Mage.php');
Mage::app();
function getCategoryTree($recursionLevel, $storeId = 1)
{
$parent = Mage::app()->getStore()->getRootCategoryId();
$tree = Mage::getResourceModel('catalog/category_tree');
/* #var $tree Mage_Catalog_Model_Resource_Category_Tree */
$nodes = $tree->loadNode($parent)
->loadChildren($recursionLevel)
->getChildren();
$tree->addCollectionData(null, false, $parent);
$categoryTreeData = array();
foreach ($nodes as $node) {
$categoryTreeData[$node->getData('entity_id')] = getNodeChildrenData($node);
}
return $categoryTreeData;
}
function getNodeChildrenData(Varien_Data_Tree_Node $node)
{
$data = array(
'title' => $node->getData('name'),
'url' => $node->getData('url_key'),
);
foreach ($node->getChildren() as $childNode) {
if (!array_key_exists('children', $data)) {
$data['children'] = array();
}
$data['children'][$childNode->getData('entity_id')] = getNodeChildrenData($childNode);
}
return $data;
}
print_r(json_encode(getCategoryTree(3)));
I've been working on some code today where I got stuck at a little multidimensional array problem. First of all it's maybe handy to read some code I wrote to get a better view on the problem itself:
public function treeLeaves(array $elements, $parent = 0) {
$branch = array();
foreach($elements as $element) {
$leaf = array('pageid' => $element['pageid'],
'page_parent' => $element['page_parent'],
'label' => ucfirst($element['page_print'][0]['print_title']),
'uri' => $element['page_alias']);
if($element['page_parent'] == $parent) {
$children = $this->treeLeaves($elements, $leaf['pageid']);
if($children) {
foreach($children as $key => $child) {
$leaf['pages'][] = $children[$key];
}
}
$branch[] = $leaf;
}
}
return $branch; }
For some reason I can't figure out how to glue the parent URI alias onto all the separate child URIs. The desired result I'm looking for should look something like this: http://pastebin.com/Eh9ExBjG
I hope some master can help me out here. I've been trying so many different stuff, but can't figure this thing out, even though I feel that it is relatively easy to solve.
Somewhat simplified, but I think you would get the idea:
function treeLeaves($elements, $parent = 0, $baseUri = '/index') {
$branch = array();
foreach($elements as $element) {
if ($element['page_parent'] == $parent) {
$leaf = array(
'uri' => $baseUri . '/' . $element['page_alias'];
);
$leaf['pages'] = treeLeaves($elements, $element['pageid'], $leaf['uri']);
$branch[] = $leaf;
}
}
return $branch;
}
I have a json feed that is more or less a list of objects
each has it's own id and idParent. objects that have idParent of null are the base parent elements. What I'm trying to achieve is to make a proper multidimensional array like a tree view. Keep in mind that children can have children too.
{
"obj1":{
"idParent":null,
"id":"parent1"
},
"obj2":{
"idParent":null,
"id":"parent2"
},
"obj3":{
"idParent":null,
"id":"parent3"
},
"obj4":{
"idParent":null,
"id":"parent4"
},
"obj5":{
"idParent":null,
"id":"parent5"
},
"obj6":{
"idParent":"parent1",
"id":"layer1-1"
},
"obj7":{
"idParent":"parent1",
"id":"layer1-2"
},
"obj8":{
"idParent":"parent2",
"id":"layer1-3"
},
"obj9":{
"idParent":"parent4",
"id":"layer1-4"
},
"obj10":{
"idParent":"parent3",
"id":"layer1-5"
},
"obj11":{
"idParent":"layer1-1",
"id":"layer2-1"
},
"obj12":{
"idParent":"parent5",
"id":"layer2-2"
},
"obj13":{
"idParent":"layer1-4",
"id":"layer2-3"
},
"obj14":{
"idParent":"layer1-5",
"id":"layer2-4"
},
"obj15":{
"idParent":"layer1-5",
"id":"layer2-5"
}
}
I've managed to filter out the root parents but after that I fail very bad
The first function does filter out the root parent nodes with idParent of null.
function decodeData($data) {
global $out;
foreach ($data as $key => $obj) {
if (is_array($obj)) {
foreach ($obj as $prop => $value) {
if ($prop == 'idParent') {
if($value == null) {
array_push($out, $obj);
unset($data[$key]);
}
}
}
}
}
if (count($data) > 0) {
decodeData($data);
} else {
echo json_encode(array('length'=>count($data)));
}
}
And this is what I'm experimenting on with no result
function decodeData($arrays) {
global $out;
foreach ($arrays as $array_name => $arr) {
foreach ($arr as $arr_prop => $arr_val) {
if ($arr_prop == 'idParent' && $arr_val == null) { // we found root parents
array_push($out, $arr);
unset($arrays[$array_name]); //remove array from the list
} else { // check if idParent is inside out
foreach ($out as $out_arr_name => $out_arr) { // iterate through out arrays
foreach ($out_arr as $out_arr_prop => $out_prop_val) { //
if ($out_arr_prop == 'id' && $arr_prop == 'idParent' && $out_arr_val == $arr_val) {
array_push($out_arr['children'], $obj);
unset($arrays[$array_name]);
}
}
}
}
}
}
if (count($arrays) > 0) {
decodeData($arrays);
} else {
echo json_encode(array('length'=>count($arrays)));
}
}
If anyone could provide some help I would really appreciate it.
I couldn't figure out what output do you want, so I just made a simple tree structure:
$data = json_decode( $your_json_string );
// Store each element in a lookup table indexed by element id
// 0th pass: put a fake root element there
$by_id = array(
'*' => new stdclass
);
// First pass: put each element into there
foreach( $data as $o ) $by_id[ $o->id ] = $o;
// Second pass: add each element into its parent's children array
foreach( $data as $o ){
$pid = $o->idParent ? $o->idParent : '*';
$p = $by_id[ $pid ];
$p->children[] = $o;
}
// Trash everything else, we start from the (fake) root element:
$tree = $by_id['*']->children;
/**** REVERSE ****/
$todo = $tree;
$json = array();
while( $todo ){
$o = array_shift( $todo );
if( isset( $o->children )){
$todo = array_merge( $todo, $o->children );
unset( $o->children );
}
$json[] = $o;
};
echo json_encode( $json );
The result:
http://codepad.viper-7.com/V7PjDh